# Select: Доступность

## Ответственность

### Встроено

- `role="combobox"` на триггере с `aria-haspopup`, `aria-expanded` и `aria-controls`, указывающим на список
- активный вариант через `aria-activedescendant`, пока фокус остаётся на триггере
- `role="listbox"` и `role="option"` с `aria-selected` и `aria-disabled`
- вся клавиатурная модель ниже, включая [поиск при наборе](https://vega-ui.dev/ru/docs/glossary/#поиск-по-вводу-typeahead)

### С вашей стороны

- доступное имя: видимый `Label` или `aria-label`
- `SelectHiddenSelect`, когда значение уходит в нативную форму
- `typeahead={false}`, когда в списке есть текстовое поле
- повторная проверка фокуса и закрытия, когда `Select` стоит внутри оверлея

## Подписи

`Select` — интерактивный элемент выбора. Его контракт доступности зависит от полной композиции [составного компонента](https://vega-ui.dev/ru/docs/glossary/#составной-компонент-compound-component), а не только от корня.

У `Select` всегда должно быть доступное имя.

Рекомендуемые паттерны:

- видимая подпись, связанная с элементом в окружающем макете формы
- поясняющее предложение для варианта `inline`, когда смысл очевиден
- дополнительный вспомогательный текст или текст ошибки, связанный через окружающую семантику формы

Если видимый интерфейс не даёт понятной подписи, добавьте её на уровне интеграции до релиза.

## Поведение клавиатуры

| Клавиша | Действие |
| --- | --- |
| <kbd>↓</kbd> / <kbd>↑</kbd> / <kbd>Enter</kbd> / <kbd>Space</kbd> | На закрытом комбобоксе: открывает список и делает активным выбранный вариант или первый. Фокус остаётся на комбобоксе. |
| <kbd>↓</kbd> / <kbd>↑</kbd> | В открытом списке: переносит активный вариант на следующий или предыдущий доступный и останавливается на краях. |
| <kbd>Home</kbd> / <kbd>End</kbd> | Делает активным первый или последний доступный вариант и открывает список, если он закрыт. |
| <kbd>Page Down</kbd> / <kbd>Page Up</kbd> | Переносит активный вариант на 10 вариантов вниз или вверх, останавливаясь на последнем или первом. |
| <kbd>s</kbd> | Поиск при наборе: печатный символ делает активным следующий вариант, чья подпись начинается с набранного текста; быстро набранные символы складываются. На закрытом комбобоксе он также открывает список, не выбирая вариант. |
| <kbd>Enter</kbd> / <kbd>Space</kbd> | В открытом списке: выбирает активный вариант и закрывает список. Фокус остаётся на комбобоксе. |
| <kbd>Escape</kbd> | Закрывает список, не меняя значение. Фокус остаётся на комбобоксе. |
| <kbd>Alt</kbd> + <kbd>↑</kbd> | Закрывает список, не меняя значение. |
| <kbd>Tab</kbd> | В открытом списке: выбирает активный вариант, если к нему перешли с клавиатуры, закрывает список и переносит фокус дальше. |

Если внутри списка рендерится настоящее текстовое поле, встроенный [поиск при наборе](https://vega-ui.dev/ru/docs/glossary/#поиск-по-вводу-typeahead) обычно стоит отключить через `typeahead={false}`, чтобы избежать конфликтов в поведении клавиатуры.

## Поведение фокуса

Фокус должен оставаться предсказуемым во всех составных частях.

- `SelectCombobox` — основная цель фокуса
- фокус остаётся на `SelectCombobox`, который указывает на активный вариант через `aria-activedescendant`
- поле формы внутри `SelectListbox`, например поле поиска, может получить фокус, и список закрывается, когда фокус его покидает
- закрытие списка должно возвращать пользователя к понятному состоянию триггера

Если `Select` рендерится внутри оверлеев вроде `Dialog`, перепроверьте восстановление фокуса и порядок табуляции в реальной композиции, а не только изолированно.

## Семантика вариантов

`SelectOption` должен оставаться единицей выбора.

- не разбивайте один вариант на несколько конкурирующих целей фокуса
- насыщенное содержимое варианта допустимо, но вариант всё равно должен вести себя как одна выбираемая строка
- отключённые варианты должны оставаться визуально и поведенчески различимыми

## Семантика для скринридеров

- триггер должен ясно сообщать назначение поля через свою подпись
- выбранное значение должно оставаться понятным без опоры на визуальный макет
- насыщенное содержимое варианта всё равно должно читаться как один вариант выбора, а не как несколько элементов управления
- плейсхолдер не должен быть единственным источником смысла поля

## Семантика форм

Используйте `SelectHiddenSelect`, когда значение должно участвовать в нативном [участии в форме](https://vega-ui.dev/ru/docs/glossary/#участие-в-форме-form-participation).

Это особенно важно для:

- обычных сценариев отправки HTML-формы
- ожиданий браузерного автозаполнения или инструментов для форм
- интеграций, читающих `FormData`

Без `SelectHiddenSelect` компонент может визуально работать, но семантика формы становится слабее.

## Вариант inline

`Select variant='inline'` используйте, только когда окружающее предложение уже придаёт элементу ясный смысл.

Хороший паттерн:

- «Уведомлять меня [еженедельно] об обновлениях».

Слабый паттерн:

- встроенный элемент без подписи и без окружающего контекста

## Отключённое состояние и только для чтения

[`disabled`](https://vega-ui.dev/ru/docs/glossary/#отключённый-disabled) и [`readOnly`](https://vega-ui.dev/ru/docs/glossary/#только-для-чтения-read-only) не равнозначны.

- `disabled`: полностью блокирует взаимодействие
- `readOnly`: сохраняет фокусируемость, но запрещает менять значение

Используйте состояние, соответствующее задуманному пользовательскому опыту. Не используйте `readOnly` как визуальную замену `disabled`.

## Паттерн списка с поиском

При встраивании поля поиска в `SelectListbox`:

- отключите встроенный поиск при наборе
- устраните конфликты клавиатуры между полем поиска и навигацией по вариантам
- убедитесь, что отфильтрованные результаты остаются доступными с клавиатуры
- сохраните видимую индикацию фокуса и для поля, и для вариантов

## Риски доступности

- отсутствующая или неоднозначная подпись
- отсутствие `SelectHiddenSelect` в сценариях с нативной формой
- встраивание текстового поля в список без отключения [поиска при наборе](https://vega-ui.dev/ru/docs/glossary/#поиск-по-вводу-typeahead)
- рендер `Select` внутри оверлеев без повторной проверки фокуса и закрытия
- насыщенное содержимое варианта, которое визуально выглядит интерактивным в нескольких местах
