НачалоОсновыКомпонентыТексты

Combobox

Combobox позволяет выбрать один пункт из длинного списка: человек печатает, и список фильтруется. Значение всегда один из ваших пунктов; введённый текст только помогает его найти.

Стабильный Figma
ОбзорИспользованиеAPIДоступность
<tk-field label="Country">
  <tk-combobox name="country" placeholder="Start typing a country">
    <option value="dk">Denmark</option>
    <option value="de">Germany</option>
    <option value="nl">Netherlands</option>
    <option value="gb">United Kingdom</option>
  </tk-combobox>
</tk-field>

Поместите combobox в Field, чтобы у него были подпись, подсказка и ошибка. Без Field задайте aria-label. Placeholder не заменяет имя: он пропадает, как только человек начинает печатать.

Анатомия

Часть Что это
tk-combobox сам элемент; одна остановка Tab
поле текстовое поле: показывает выбранный пункт или то, что человек печатает; занимает ширину контейнера
кнопка очистки видна, пока в поле есть текст; стирает текст и значение
шеврон переворачивается, пока меню открыто; во время загрузки пунктов его место занимает спиннер
меню подходящие пункты; ширина как у поля; открывается под полем, а у нижнего края экрана над ним
пункт одна строка; выбранный отмечает галочка
заголовок группы необязательный заголовок над несколькими пунктами; скрыт, если ни один из них не подошёл
строка сообщения «No results found», подсказка о загрузке или ошибка загрузки; её нельзя выбрать

В меню видно примерно пять с половиной строк, дальше оно прокручивается.

Размеры

<tk-combobox aria-label="City" placeholder="Start typing a city">
  <option>Amsterdam</option>
</tk-combobox>
<tk-combobox size="large" aria-label="Airport" placeholder="Start typing an airport">
  <option>Schiphol</option>
</tk-combobox>
size Высота Padding-inline Текст Строка пункта
medium (по умолчанию) 32px space-8 Body Small (14/20) 32px
large 36px space-10 Body Medium (16/24) 36px

Высоты совпадают с Select, Input и Button. Длинные пункты обрезаются многоточием.

Состояния

<tk-combobox aria-label="Office" value="lis" disabled>
  <option value="lis">Lisbon</option>
</tk-combobox>
<tk-combobox aria-label="Team" value="core" readonly>
  <option value="core">Core platform</option>
</tk-combobox>

При наведении поле не меняется. При фокусе с клавиатуры его рамка окрашивается и становится толще; кольца фокуса нет.

  • disabled: на поле нельзя перейти, его нельзя открыть, значение не отправляется.
  • readonly: значение видно и отправляется. Поле можно выделить и скопировать текст, но нельзя изменить или открыть меню. Кнопка очистки и шеврон скрыты.
  • Ошибка: задайте error на Field. Под полем появится сообщение, рамка станет красной, даже в фокусе.

Фильтрация

  • Ввод открывает меню и фильтрует его. Регистр не важен, совпадение ищется в любом месте названия: «kingdom» найдёт «United Kingdom». Описания и заголовки групп не учитываются.
  • Текст — это поиск, а не значение. Значение меняется, только когда человек выбирает пункт. Если он уходит, ничего не выбрав, в поле возвращается выбранный пункт.
  • Клик открывает весь список, так что выбрать можно и без ввода.
  • Если ничего не нашлось, меню показывает «No results found».

Источники данных

Источник Как задать Где фильтруется
дочерние <option> (по умолчанию) разметкой, группы через <optgroup> в браузере
свойство options массив { value, label, description?, disabled?, group? } в браузере
свойство loadOptions асинхронная функция, которая возвращает пункты для запроса на вашем сервере

loadOptions нужен, только если список лежит на сервере или слишком велик, чтобы отдавать его целиком:

combobox.loadOptions = async (query, { signal }) => {
  const res = await fetch(`/api/cities?q=${encodeURIComponent(query)}`, { signal });
  return (await res.json()).map((c) => ({ value: c.id, label: c.name }));
};
  • Запрос уходит через debounce мс (250) после последнего нажатия.
  • min-chars откладывает запросы, пока не введено достаточно символов; меню пишет «Type 2 or more characters.» Значение по умолчанию, 0, загружает весь список по клику.
  • Во время загрузки вместо шеврона крутится спиннер. Если промис отклонён, меню показывает «Couldn't load options.» и кнопку Try again; Enter тоже повторяет запрос.
  • Показываются только результаты последнего запроса. Передайте signal в fetch, чтобы отменять старые.
  • Возвращайте уже отфильтрованные пункты, каждый в одну строку.

Описания пунктов

<tk-combobox aria-label="Plan" placeholder="Start typing a plan">
  <option value="free" data-description="For trying things out">Free</option>
  <option value="pro" data-description="Adds version history">Pro</option>
</tk-combobox>

data-description (или description в options) добавляет короткую вторую строку. Пишите её, чтобы помочь с выбором, и не описывайте каждый пункт. Скринридер читает её после названия.

Создание своих значений

<tk-field label="Tag">
  <tk-combobox creatable placeholder="Start typing a tag">
    <option value="design">Design</option>
    <option value="research">Research</option>
  </tk-combobox>
</tk-field>

По умолчанию можно выбрать только ваши пункты. С creatable запрос без совпадений добавляет строку Create "…". Выбор этой строки или Enter на введённом тексте делает текст значением и добавляет его в список. Подходит для открытых наборов вроде тегов или навыков.

  • При точном совпадении без учёта регистра предлагается существующий пункт, а не копия.
  • Уход из поля по Tab, Esc или клику снаружи ничего не создаёт.
  • Работает с любым источником, но не во время загрузки и не ниже min-chars.