Combobox
Combobox совмещает текстовый поиск и одиночный listbox. Ввод фильтрует варианты, но значением становится только явно выбранная опция.
Статус: experimental · в системе с 2026-07 · интерактивность: always (всегда)
Когда использовать
- Плоский список слишком длинный для Select и пользователь знает часть названия.
- Нужно выбрать ровно одно существующее значение, а не ввести произвольный текст.
Не использовать:
- Список короткий и быстро сканируется целиком — используй Select.
- Допустим произвольный текст — используй Input.
- Нужен набор значений — используй Multi Select.
- Варианты образуют иерархию — используй Tree Select.
Альтернативы:
select— короткий известный список без фильтрацииinput— произвольное значение, которого может не быть в справочникеmulti-select— несколько значений из плоского списка
Базовый
Одиночный выбор из длинного списка городов.
<!--
🟢
Базовый пример Combobox показывает подтверждённое одиночное значение из
длинного списка. Выбранный город остаётся отдельным от поискового запроса.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import Combobox from "$lib/ui/Combobox.svelte";
let city = $state("kzn");
const cities = [
{ value: "msk", label: t("Москва") },
{ value: "spb", label: t("Санкт-Петербург") },
{ value: "nsk", label: t("Новосибирск") },
{ value: "ekb", label: t("Екатеринбург") },
{ value: "kzn", label: t("Казань") },
{ value: "nng", label: t("Нижний Новгород") },
{ value: "che", label: t("Челябинск") },
{ value: "smr", label: t("Самара") },
];
</script>
<div style="width: var(--control-field-min);">
<Combobox label={t("Город")} options={cities} bind:value={city} />
</div>
Фильтрация
Запрос сужает список, но не становится значением.
<!--
🟢
Пример фильтрации отделяет временный запрос от значения Combobox. Текст,
которого нет среди вариантов, не становится результатом поля.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import Combobox from "$lib/ui/Combobox.svelte";
let framework = $state("");
const frameworks = [
{ value: "svelte", label: "Svelte" },
{ value: "vue", label: "Vue" },
{ value: "react", label: "React" },
{ value: "angular", label: "Angular" },
{ value: "solid", label: "Solid" },
{ value: "preact", label: "Preact" },
{ value: "ember", label: "Ember" },
];
</script>
<div style="width: var(--control-field-min);">
<Combobox
label={t("Фреймворк")}
placeholder={t("Начните вводить название")}
emptyMessage={t("Совпадений нет.")}
options={frameworks}
bind:value={framework}
/>
</div>
Поле
Подсказка, обязательность, описание и ошибка.
<!--
🟢
Пример поля Combobox собирает служебные состояния формы. Подсказка,
описание, обязательность и ошибка не меняют модель одиночного выбора.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import Combobox from "$lib/ui/Combobox.svelte";
let requiredCity = $state("");
let invalidCity = $state("");
const cities = [
{ value: "msk", label: t("Москва") },
{ value: "spb", label: t("Санкт-Петербург") },
{ value: "nsk", label: t("Новосибирск") },
{ value: "ekb", label: t("Екатеринбург") },
{ value: "kzn", label: t("Казань") },
];
</script>
<div style="display: grid; gap: var(--sp-3); width: var(--control-field-min);">
<Combobox
label={t("Обязательный город")}
hint={t("Выберите существующий город")}
description={t("Поиск работает по названию.")}
name="city"
required
options={cities}
bind:value={requiredCity}
/>
<Combobox
label={t("Город")}
error={t("Выберите город из списка.")}
options={cities}
bind:value={invalidCity}
/>
</div>
Очистка и загрузка
clearable сбрасывает выбор крестиком; loading показывает скелетон в меню.
<!--
🟢
Очистка и загрузка (эталон: Vue-легаси select/live): крестик сбрасывает
выбор, `loading` показывает скелетон в меню, пока приложение готовит
список.
-->
<script>
import { t } from "$lib/spec/demo-lang.svelte.js";
import Combobox from "$lib/ui/Combobox.svelte";
const options = Array.from({ length: 10 }, (_, i) => ({ value: `u${i + 1}`, label: `${t("Пользователь")} ${i + 1}` }));
let value = $state("u2");
let loading = $state(false);
</script>
<div style="display: flex; flex-direction: column; gap: var(--sp-2); width: 320px;">
<Combobox label={t("Менеджер")} {options} bind:value clearable {loading} />
<label style="font-size: var(--fs-xs);"><input type="checkbox" bind:checked={loading} /> loading</label>
</div>