Поддержка скринридеров

Tom Select изначально проектируется как замена стандартного <select>, и одна из ключевых задач при его использовании в продакшене — корректная работа со скринридерами. Доступность в данном контексте определяется не только наличием ARIA-атрибутов, но и тем, как библиотека управляет фокусом, динамическими изменениями DOM и семантикой интерактивных элементов.

Основной доступный паттерн, на который опирается Tom Select, — это combobox. В контексте скринридеров он описывает комбинированное поле ввода, связанное со списком вариантов.

Ключевые роли:

  • role="combobox" — контейнер инпута
  • role="listbox" — выпадающий список
  • role="option" — элементы списка

Связка этих ролей формирует базовую навигационную модель:

  • инпут управляет раскрытием списка
  • список объявляется как набор опций
  • активная опция меняется через клавиатуру

Особое значение имеет атрибут:

  • aria-expanded — отражает состояние раскрытия списка

При изменении состояния важно, чтобы скринридер немедленно получал обновление, иначе пользователь теряет контекст взаимодействия.

Управление фокусом и виртуальная навигация

В скринридерах критична предсказуемость фокуса. Tom Select использует модель, при которой:

  • фокус остается в input-элементе
  • перемещение по списку осуществляется виртуально
  • активный элемент изменяется логически, а не через реальный DOM focus shift

Это предотвращает:

  • «скачки» фокуса
  • потерю позиции в списке
  • прерывание режима чтения скринридера

При навигации стрелками:

  • ArrowDown / ArrowUp меняют активную опцию
  • Enter подтверждает выбор
  • Escape закрывает список

С точки зрения accessibility, важно, что активный элемент синхронизируется с:

  • aria-activedescendant

Этот атрибут связывает input с текущим пунктом списка без физического перемещения фокуса.

Объявления изменений через aria-live

Динамическое содержимое — одна из самых проблемных зон для скринридеров. В Tom Select обновления списка, фильтрации и состояния выбора сопровождаются использованием live-регионов.

Чаще всего применяются:

  • aria-live="polite" для ненавязчивых обновлений
  • aria-live="assertive" только для критических изменений

Типичные события, которые должны быть озвучены:

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

Пример логики:

  • пользователь вводит текст
  • список фильтруется
  • скринридеру сообщается: «найдено 5 элементов»

Если этого не происходит, пользователь со скринридером фактически не понимает, изменился ли результат ввода.

Работа с multi-select и тегами

В режиме множественного выбора появляются дополнительные элементы интерфейса — «теги» выбранных значений.

Каждый тег должен быть:

  • фокусируемым при удалении (или содержать кнопку удаления)
  • доступным по имени через aria-label
  • корректно описанным для чтения скринридером

Типичная структура:

  • контейнер тега: role="option" или нейтральный span с описанием
  • кнопка удаления: aria-label="Удалить [значение]"

Важный момент: удаление элемента должно сопровождаться объявлением изменения списка:

  • «значение удалено»
  • «осталось N элементов»

Без этого пользователь теряет понимание состояния выбора.

Подсказки и описание через aria-describedby

Поле ввода в Tom Select часто требует пояснений:

  • формат ввода
  • допустимые значения
  • ограничения поиска

Для этого используется:

  • aria-describedby

Он связывает input с дополнительным текстовым блоком, который может содержать:

  • инструкцию по вводу
  • описание фильтрации
  • ограничения выбора

Это особенно важно при асинхронной загрузке данных, когда пользователь не видит полного списка заранее.

Управление состоянием disabled и readonly

Состояния недоступности должны быть явно отражены:

  • aria-disabled="true" — логическая блокировка
  • disabled — физическое отключение input

В контексте скринридеров важно различать:

  • полностью недоступное поле
  • поле только для чтения

Неправильная семантика приводит к тому, что скринридер может позволить пользователю взаимодействие с элементом, который фактически заблокирован.

Поиск и фильтрация: доступность результата

Фильтрация в Tom Select часто происходит асинхронно или с задержкой.

Проблемная зона — момент, когда:

  • пользователь вводит текст
  • список временно пуст
  • затем данные догружаются

Для корректной работы необходимо:

  • объявлять состояние загрузки (loading)
  • сообщать о результате поиска

Типовые сообщения:

  • «поиск…»
  • «результаты обновлены»
  • «ничего не найдено»

Без этого скринридер воспринимает промежуточное состояние как финальное.

ARIA-структура списка опций

Каждый элемент списка обязан содержать:

  • role="option"
  • уникальный id (для aria-activedescendant)
  • состояние выбора через aria-selected

Пример логики состояний:

  • не выбран: aria-selected="false"
  • выбран: aria-selected="true"

Дополнительно важно:

  • не дублировать текст внутри option и label input без необходимости
  • избегать вложенных интерактивных элементов внутри option

Скринридеры некорректно обрабатывают вложенную интерактивность, что приводит к «разрыву» навигации.

Поддержка клавиатурных режимов скринридеров

Скринридеры часто используют собственные режимы навигации:

  • виртуальный курсор
  • режим форм
  • режим обзора страницы

Tom Select должен корректно работать во всех трёх.

Критические требования:

  • список не должен перехватывать фокус
  • стрелки должны работать предсказуемо
  • Escape всегда возвращает состояние к закрытому списку

Особое внимание уделяется:

  • предотвращению «залипания» фокуса в списке
  • корректному возврату к input после выбора

Обновление DOM без потери контекста

Одной из типичных проблем является пересоздание DOM-узлов при фильтрации.

Если элементы пересоздаются без сохранения:

  • aria-activedescendant
  • aria-selected
  • стабильных id

скринридер теряет позицию пользователя.

Поэтому предпочтительно:

  • переиспользование элементов списка
  • минимизация полной перерисовки
  • стабильные идентификаторы опций

Асинхронные источники данных и скринридеры

При подключении remote-данных (AJAX, fetch) возникают дополнительные требования:

  • объявление начала загрузки
  • объявление завершения загрузки
  • обработка ошибки сети

Скринридер должен понимать:

  • список временно недоступен
  • данные обновляются
  • результат готов

Иначе пользователь получает «тишину интерфейса», что воспринимается как зависание.

Фокус после выбора значения

После выбора элемента важно определить поведение фокуса:

  • в одиночном выборе: фокус остается в input
  • в multi-select: фокус может оставаться в поле ввода или переходить к следующему вводу формы

Критично избегать:

  • потери фокуса в документ
  • перехода в неочевидные элементы UI

Также необходимо обновлять:

  • текстовое значение input
  • список выбранных элементов
  • aria-описания состояния

Особенности удаления элементов с клавиатуры

Удаление тегов через клавиатуру должно быть предсказуемым:

  • Backspace удаляет последний тег при пустом input
  • Delete удаляет выделенный элемент (если поддерживается)

При этом скринридеру необходимо сообщать:

  • какой элемент удалён
  • сколько осталось

Без этого пользователь не понимает, какое именно действие произошло.

Согласованность визуального и доступного состояния

Важный принцип: визуальное состояние всегда должно соответствовать ARIA-состоянию.

Несоответствия:

  • открытый список, но aria-expanded="false"
  • выбранный элемент без aria-selected
  • скрытый элемент, но присутствующий в listbox

приводят к полному разрыву модели восприятия интерфейса скринридером.


Корректная реализация поддержки скринридеров в Tom Select строится на строгом соблюдении ARIA-модели combobox, предсказуемом управлении фокусом, непрерывных текстовых объявлениях изменений и стабильной структуре DOM, в которой каждое состояние интерфейса отражается одновременно визуально и семантически.