Перейти до вмісту
tatetUI

Select

Випадний список із фільтрацією, повною клавіатурною навігацією та ARIA-combobox.

Єдиний серед чотирьох вихідних проєктів компонент із повноцінним ARIA-combobox. Решта реалізацій були <div> із випадайкою — візуально схоже, для скрінрідера не існує.

Приклад

Список звужується під час набору.

API

Props

НазваТипТиповоОпис
options*SelectOption[]Варіанти вибору. Фільтрація за введеним текстом відбувається локально.
modelValuestring | numberОбране значення. Використовуйте через `v-model`.
labelstring
placeholderstring
sizeFieldSize"md"Висота поля. На мобільному кожен розмір вищий за десктопний.
errorstringТекст помилки. Його наявність вмикає стан помилки.
hintstringПідказка під полем. Ховається, коли показано помилку.
idstringСтабільний DOM id. `name` використовується лише для форми.
namestring
disabledboolean
requiredboolean
loadingbooleanПоказує індикатор замість списку — для серверного пошуку.
clearablebooleanДозволяє скинути вибір хрестиком.
filterablebooleantrueДозволяє звужувати список набором тексту.

Події

НазваPayloadОпис
search[query: string]Введений текст. Підключайте для серверної фільтрації.
update:modelValue[value: string | number]Обране значення або `null`, якщо вибір скинуто.

Слоти

НазваОпис
optionВласний рендер пункту списку.

Доступно через ref

НазваТипОпис
focus() => voidСтавить фокус на поле.

Коли використовувати

Для вибору одного значення з відомого набору. Від приблизно семи пунктів вмикайте filterable — гортати довгий список гірше, ніж набрати три букви.

Коли НЕ використовувати

Для двох-трьох варіантів беріть радіокнопки: вони показують усі варіанти одразу, без зайвого кліку.

Для довільного тексту з підказками потрібен інший компонент — цей завжди повертає значення зі списку.

Доступність

Поле має role="combobox", aria-autocomplete="list", aria-expanded, aria-controls і aria-activedescendant. Панель — role="listbox", пункти — role="option" з aria-selected.

Стрілки пропускають деактивовані пункти, а не зупиняються на них. Escape викликає stopPropagation — інакше той самий натиск закрив би ще й модалку, у якій селект стоїть.

Панель телепортується в body. Базовий шар — 1100, а всередині вкладеного Modal або Drawer значення автоматично піднімається над найближчим оверлеєм.

Деталі реалізації

Позиція рахується власним кодом, без @floating-ui і без VueUse — компонент має копіюватись у чужий проєкт без нової залежності.

Слухач прокрутки навішено з capture: true. Подія scroll не спливає, тож без цього відкрита панель лишалася б висіти на місці, поки список під нею від'їжджає.

Позиція вимірюється двічі: перший раз із припущенням висоти 240px, другий — коли панель уже отримала реальну. Без другого проходу вибір напрямку відкриття інколи помилявся.

Поки користувач не почав набирати, показується весь список. Інакше після відкриття видно лише один пункт — той, що вже обраний і чия назва стоїть у полі як текст фільтра.