Select
Випадний список із фільтрацією, повною клавіатурною навігацією та ARIA-combobox.
Єдиний серед чотирьох вихідних проєктів компонент із повноцінним
ARIA-combobox. Решта реалізацій були <div> із випадайкою — візуально
схоже, для скрінрідера не існує.
Приклад
Список звужується під час набору.
API
Props
| Назва | Тип | Типово | Опис |
|---|---|---|---|
options* | SelectOption[] | — | Варіанти вибору. Фільтрація за введеним текстом відбувається локально. |
modelValue | string | number | — | Обране значення. Використовуйте через `v-model`. |
label | string | — | — |
placeholder | string | — | — |
size | FieldSize | "md" | Висота поля. На мобільному кожен розмір вищий за десктопний. |
error | string | — | Текст помилки. Його наявність вмикає стан помилки. |
hint | string | — | Підказка під полем. Ховається, коли показано помилку. |
id | string | — | Стабільний DOM id. `name` використовується лише для форми. |
name | string | — | — |
disabled | boolean | — | — |
required | boolean | — | — |
loading | boolean | — | Показує індикатор замість списку — для серверного пошуку. |
clearable | boolean | — | Дозволяє скинути вибір хрестиком. |
filterable | boolean | true | Дозволяє звужувати список набором тексту. |
Події
| Назва | 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, другий — коли панель уже отримала реальну. Без другого проходу вибір напрямку відкриття інколи помилявся.
Поки користувач не почав набирати, показується весь список. Інакше після відкриття видно лише один пункт — той, що вже обраний і чия назва стоїть у полі як текст фільтра.