Ответственность
Встроено
role="combobox"на триггере сaria-haspopup,aria-expandedиaria-controls, указывающим на список- активный вариант через
aria-activedescendant, пока фокус остаётся на триггере role="listbox"иrole="option"сaria-selectedиaria-disabled- вся клавиатурная модель ниже, включая поиск при наборе
С вашей стороны
- доступное имя: видимый
Labelилиaria-label SelectHiddenSelect, когда значение уходит в нативную формуtypeahead={false}, когда в списке есть текстовое поле- повторная проверка фокуса и закрытия, когда
Selectстоит внутри оверлея
Подписи
Select — интерактивный элемент выбора. Его контракт доступности зависит от полной композиции составного компонента, а не только от корня.
У Select всегда должно быть доступное имя.
Рекомендуемые паттерны:
- видимая подпись, связанная с элементом в окружающем макете формы
- поясняющее предложение для варианта
inline, когда смысл очевиден - дополнительный вспомогательный текст или текст ошибки, связанный через окружающую семантику формы
Если видимый интерфейс не даёт понятной подписи, добавьте её на уровне интеграции до релиза.
Поведение клавиатуры
| Клавиша | Действие |
|---|---|
| ↓↑EnterSpace | На закрытом комбобоксе: открывает список и делает активным выбранный вариант или первый. Фокус остаётся на комбобоксе. |
| ↓↑ | В открытом списке: переносит активный вариант на следующий или предыдущий доступный и останавливается на краях. |
| HomeEnd | Делает активным первый или последний доступный вариант и открывает список, если он закрыт. |
| Page DownPage Up | Переносит активный вариант на 10 вариантов вниз или вверх, останавливаясь на последнем или первом. |
| s | Поиск при наборе: печатный символ делает активным следующий вариант, чья подпись начинается с набранного текста; быстро набранные символы складываются. На закрытом комбобоксе он также открывает список, не выбирая вариант. |
| EnterSpace | В открытом списке: выбирает активный вариант и закрывает список. Фокус остаётся на комбобоксе. |
| Escape | Закрывает список, не меняя значение. Фокус остаётся на комбобоксе. |
| Alt + ↑ | Закрывает список, не меняя значение. |
| Tab | В открытом списке: выбирает активный вариант, если к нему перешли с клавиатуры, закрывает список и переносит фокус дальше. |
Если внутри списка рендерится настоящее текстовое поле, встроенный поиск при наборе обычно стоит отключить через typeahead={false}, чтобы избежать конфликтов в поведении клавиатуры.
Поведение фокуса
Фокус должен оставаться предсказуемым во всех составных частях.
SelectCombobox— основная цель фокуса- фокус остаётся на
SelectCombobox, который указывает на активный вариант черезaria-activedescendant - поле формы внутри
SelectListbox, например поле поиска, может получить фокус, и список закрывается, когда фокус его покидает - закрытие списка должно возвращать пользователя к понятному состоянию триггера
Если Select рендерится внутри оверлеев вроде Dialog, перепроверьте восстановление фокуса и порядок табуляции в реальной композиции, а не только изолированно.
Семантика вариантов
SelectOption должен оставаться единицей выбора.
- не разбивайте один вариант на несколько конкурирующих целей фокуса
- насыщенное содержимое варианта допустимо, но вариант всё равно должен вести себя как одна выбираемая строка
- отключённые варианты должны оставаться визуально и поведенчески различимыми
Семантика для скринридеров
- триггер должен ясно сообщать назначение поля через свою подпись
- выбранное значение должно оставаться понятным без опоры на визуальный макет
- насыщенное содержимое варианта всё равно должно читаться как один вариант выбора, а не как несколько элементов управления
- плейсхолдер не должен быть единственным источником смысла поля
Семантика форм
Используйте SelectHiddenSelect, когда значение должно участвовать в нативном участии в форме.
Это особенно важно для:
- обычных сценариев отправки HTML-формы
- ожиданий браузерного автозаполнения или инструментов для форм
- интеграций, читающих
FormData
Без SelectHiddenSelect компонент может визуально работать, но семантика формы становится слабее.
Вариант inline
Select variant='inline' используйте, только когда окружающее предложение уже придаёт элементу ясный смысл.
Хороший паттерн:
- «Уведомлять меня [еженедельно] об обновлениях».
Слабый паттерн:
- встроенный элемент без подписи и без окружающего контекста
Отключённое состояние и только для чтения
disabled и readOnly не равнозначны.
disabled: полностью блокирует взаимодействиеreadOnly: сохраняет фокусируемость, но запрещает менять значение
Используйте состояние, соответствующее задуманному пользовательскому опыту. Не используйте readOnly как визуальную замену disabled.
Паттерн списка с поиском
При встраивании поля поиска в SelectListbox:
- отключите встроенный поиск при наборе
- устраните конфликты клавиатуры между полем поиска и навигацией по вариантам
- убедитесь, что отфильтрованные результаты остаются доступными с клавиатуры
- сохраните видимую индикацию фокуса и для поля, и для вариантов
Риски доступности
- отсутствующая или неоднозначная подпись
- отсутствие
SelectHiddenSelectв сценариях с нативной формой - встраивание текстового поля в список без отключения поиска при наборе
- рендер
Selectвнутри оверлеев без повторной проверки фокуса и закрытия - насыщенное содержимое варианта, которое визуально выглядит интерактивным в нескольких местах