MultiSelect
Мультивибір із чекбоксами, пошуком, діями «вибрати все / зняти все» та лічильником у тригері.
Мультивибір збирає найкраще з двох джерел: поведінку (пошук, «вибрати все», згортання вибору в «+N») успадковано з продуктової реалізації, позиціонування й ARIA-listbox — з канонічного UiSelect.
Приклад
Обрано: editor
API
Props
| Назва | Тип | Типово | Опис |
|---|---|---|---|
modelValue* | (string | number)[] | — | Обрані значення. Використовуйте через `v-model`. |
options* | MultiSelectOption[] | — | Варіанти вибору. Фільтрація за введеним текстом відбувається локально. |
label | string | — | — |
placeholder | string | "Оберіть" | — |
size | FieldSize | "md" | Висота поля. На мобільному кожен розмір вищий за десктопний. |
maxDisplay | number | 3 | Скільки обраних підписів показати у тригері, решта згортається в «+N». |
error | string | — | Текст помилки. Сама його наявність вмикає стан помилки. |
hint | string | — | Підказка під полем. Ховається, коли показано помилку. |
id | string | — | Стабільний DOM id. `name` використовується лише для форми. |
name | string | — | — |
disabled | boolean | false | — |
required | boolean | false | Потрібен хоча б один вибір: зірочка, `aria-required` і нативна перевірка форми — через невидимий проксі-інпут, бо `type="hidden"` у валідації форми участі не бере. |
searchable | boolean | true | Поле пошуку всередині панелі. Для списків ≤5 пунктів не показується навіть із `true` — пошук там лише заважає. |
mobileSheet | boolean | true | На вузькому екрані (до 768px) список відкривається нижнім sheet'ом на всю ширину з кнопкою «Готово» замість випадайки під полем. |
Події
| Назва | Payload | Опис |
|---|---|---|
update:modelValue | [value: (string | number)[]] | Масив обраних значень у порядку, заданому в `options`. |
Слоти
| Назва | Опис |
|---|---|
option | Власний рендер пункту списку. |
Доступно через ref
| Назва | Тип | Опис |
|---|---|---|
focus | () => void | Ставить фокус на тригер. |
Коли використовувати
Коли користувач обирає ДЕКІЛЬКА значень із відомого набору: ролі, теги, фільтри за статусами. Лічильник у тригері показує масштаб вибору, коли підписи вже не вміщаються.
Коли НЕ використовувати
Для одного значення потрібен Select — два контроли з однаковим виглядом, але різною семантикою, плутають.
Для 2–3 взаємновиключних варіантів беріть чекбокси просто в формі: вони показують усі варіанти одразу, без кліку.
На мобільному
До 768px список відкривається нижнім sheet'ом, як у Select:
рядки по 48px із чекбоксом 20px, «Вибрати все» і «Зняти все» — текстом, а не
значками (на дотику підказка title не з'являється), внизу — «Готово».
Пункти перемикаються одразу, як і у випадайці, тож «Готово» лише закриває:
окремого «Застосувати» немає, і закриття свайпом нічого не губить. Пошук —
від 11 пунктів і без автофокуса. Вимикається через :mobile-sheet="false".
Доступність
Тригер — aria-haspopup="listbox" з aria-expanded; панель —
role="listbox" з aria-multiselectable="true", пункти — role="option"
з aria-selected. Стрілки й Enter працюють по відфільтрованому списку,
Escape закриває панель і повертає фокус на тригер, не «протікаючи» в
модалку навколо (stopPropagation).
Панель закривається, щойно фокус іде за межі тригера й панелі — Tab до
наступного поля не лишає її висіти над ним. Панель телепортована в кінець
<body>, тож на її краях Tab повертає фокус на тригер: Shift+Tab із пошуку
зупиняється на тригері, а Tab з останньої кнопки йде далі вже від тригера —
до наступного поля форми, а не за межі сторінки.
required дає зірочку, aria-required на тригері й нативну перевірку
форми. Приховані <input type="hidden"> у валідації участі не беруть, тож
обов'язковість несе невидимий проксі-інпут під тригером — там браузер і
покаже свою підказку.
Помилка вмикається наявністю тексту, а не прапорцем: aria-invalid і
aria-describedby (>error-id) ставляться лише коли є що сказати.