Навигация с клавиатуры в Tom Select строится вокруг имитации
поведения нативных <select> элементов с расширением
функциональности для поиска, множественного выбора и кастомного рендера.
Основная задача механизма — обеспечить предсказуемое перемещение по
спискам опций, управление выбором без мыши и корректную работу в режимах
одиночного и множественного выбора.
Ключевой принцип реализации заключается в разделении состояния
компонента на три области: активное поле ввода, выпадающий список опций
и выбранные элементы (теги). Каждая из этих областей имеет собственную
модель фокуса и набор доступных клавиатурных действий.
Базовые клавиши и модель
фокуса
Фокус в Tom Select переключается между несколькими состояниями:
- поле ввода (input mode)
- список опций (dropdown mode)
- выбранные элементы (control/tags mode)
Основные клавиши управления:
- ArrowDown / ArrowUp — перемещение по списку
опций
- Enter — выбор активной опции
- Escape — закрытие списка
- Backspace — удаление последнего выбранного элемента
(в режиме множественного выбора)
- Tab — переход к следующему элементу формы
- Ctrl + A — выделение текста в поле ввода (в
зависимости от конфигурации)
Поведение адаптируется под состояние dropdown:
- если список закрыт, стрелки не открывают его автоматически (в
стандартной конфигурации)
- если список открыт, стрелки управляют активной подсветкой
- Enter может как открыть список, так и выбрать элемент, в зависимости
от контекста
Открытие и закрытие
списка с клавиатуры
Открытие dropdown происходит при взаимодействии с клавишами,
связанными с вводом:
- ArrowDown при закрытом списке открывает его и
устанавливает первую доступную опцию как активную
- ArrowUp аналогично открывает список, но активирует
последнюю опцию
- Alt + ArrowDown (в некоторых конфигурациях)
принудительно раскрывает список без изменения активного элемента
Закрытие списка:
- Escape закрывает dropdown и возвращает фокус в поле
ввода
- повторное нажатие Escape не изменяет состояние, если список уже
закрыт
Внутренняя логика учитывает наличие фильтрации: при открытии списка
фокус автоматически переходит в input, обеспечивая возможность
немедленного ввода текста.
Навигация по опциям
Список опций в Tom Select представляет собой виртуализируемую
структуру (в зависимости от настроек), где активный элемент
отслеживается через индекс.
Основные правила перемещения:
- ArrowDown увеличивает индекс активной опции
- ArrowUp уменьшает индекс
- при достижении конца списка происходит циклический переход (если
включён
selectOnTab или аналогичная логика)
- при фильтрации список перестраивается, и индекс пересчитывается
относительно нового массива
Псевдологика:
if (key === 'ArrowDown') {
activeIndex = Math.min(activeIndex + 1, options.length - 1);
}
if (key === 'ArrowUp') {
activeIndex = Math.max(activeIndex - 1, 0);
}
Особое поведение проявляется при поиске:
- фильтр обновляет список в реальном времени
- активная опция сбрасывается на первую подходящую
- при пустом результате навигация блокируется
Выбор элементов через
клавиатуру
Выбор опции осуществляется клавишей Enter:
- в режиме одиночного выбора Enter заменяет текущее значение
- в режиме множественного выбора Enter добавляет элемент в список
выбранных
- если включена опция
create, Enter может создавать новую
сущность
Логика выбора:
if (key === 'Enter' && activeOption) {
selectItem(activeOption);
}
При этом учитываются состояния:
- disabled-опции игнорируются
- уже выбранные элементы исключаются (если
maxItems
ограничен)
- кастомные фильтры могут блокировать выбор
Удаление элементов
клавиатурой
В режиме множественного выбора удаление реализовано через
Backspace:
- если поле ввода пустое, удаляется последний выбранный элемент
- если поле содержит текст, Backspace работает как обычное удаление
символов
- при удержании Backspace возможна последовательная очистка тегов
Логика:
if (key === 'Backspace' && inputValue === '') {
removeLastItem();
}
Также поддерживаются сценарии:
- удаление через фокус на тегах (если включён режим
remove_button)
- удаление через Shift + Delete (в кастомных конфигурациях)
Фильтрация и ввод текста
Поле ввода играет центральную роль в клавиатурной навигации:
- ввод текста автоматически открывает список
- фильтрация происходит на каждый keydown/keyup
- активная опция синхронизируется с результатами фильтрации
Поведение стрелок при активной фильтрации:
- навигация ограничена отфильтрованным набором
- при изменении текста индекс пересчитывается
- при полном несовпадении список становится пустым
Особенность реализации заключается в том, что ввод текста не
блокирует навигацию — обе операции работают параллельно.
Работа с множественным
выбором
В multi-mode клавиатурная логика усложняется из-за необходимости
управления коллекцией элементов.
Основные правила:
- Enter добавляет элемент в массив выбранных
- Backspace удаляет последний элемент при пустом input
- ArrowLeft / ArrowRight могут переключать фокус между тегами (в
кастомных конфигурациях)
- Tab может завершать редактирование текущего тега
Состояние поддерживает два уровня:
- активная опция в списке
- активный тег в выбранных элементах
Эти уровни не конфликтуют, но переключаются в зависимости от
фокуса.
Поддержка доступности
(ARIA и keyboard UX)
Клавиатурная навигация тесно связана с ARIA-атрибутами:
aria-activedescendant указывает текущую активную
опцию
role="listbox" определяет контейнер списка
role="option" применяется к каждому элементу
aria-expanded отражает состояние dropdown
Фокус не всегда перемещается физически на элементы списка; вместо
этого используется виртуальный фокус через ARIA, что обеспечивает более
стабильную навигацию.
Поведение клавиш синхронизируется с ARIA-состояниями:
- изменение активной опции обновляет
aria-activedescendant
- открытие списка меняет
aria-expanded=true
- закрытие возвращает
false
Кастомизация клавиатурных
событий
Tom Select предоставляет механизм перехвата и переопределения
клавиатурного поведения через события:
onKeyDown
onItemAdd
onItemRemove
onDropdownOpen
onDropdownClose
Пример расширения логики:
new TomSelect('#select', {
onKeyDown: function (e) {
if (e.key === 'Tab') {
this.close();
}
}
});
Также возможно полное переопределение поведения стрелок:
onKeyDown: function (e) {
if (e.key === 'ArrowDown') {
this.setActiveOption(this.getActiveOption() + 2);
}
}
Конфликты клавиш и
обработка событий
Встроенная система учитывает возможные конфликты:
- браузерные горячие клавиши (Ctrl+R, Ctrl+L) не перехватываются
- системные комбинации имеют приоритет
- события обрабатываются только при активном фокусе компонента
Обработка событий строится через последовательность:
- проверка фокуса
- определение типа состояния (open/closed/input)
- обработка keydown
- предотвращение default при необходимости
- обновление UI
Особенности поведения в
разных режимах
В single-select:
- стрелки управляют одной активной опцией
- Enter заменяет текущее значение
- Backspace не влияет на список выбранных
В multi-select:
- появляется управление коллекцией
- Backspace становится значимым действием
- Enter добавляет элементы
В режиме создания новых значений:
- Enter может создавать элемент при отсутствии совпадений
- клавиатурная логика учитывает частичное совпадение
- фильтрация не блокирует создание
Производительность
при активной навигации
При интенсивном использовании клавиатуры важно минимизировать
пересоздание DOM:
- активная опция обновляется без полной перерисовки списка
- фильтрация оптимизирована через кэширование результатов
- события батчатся при быстром вводе
Навигация стрелками не вызывает перерасчёт всего списка, изменяется
только состояние подсветки.
Типичные сценарии
взаимодействия
Сценарий последовательного выбора:
- открытие списка через ArrowDown
- перемещение по опциям
- Enter для выбора
- повтор навигации без закрытия списка
Сценарий быстрого поиска:
- ввод текста
- автоматическое открытие списка
- ArrowDown для первого результата
- Enter для подтверждения
Сценарий очистки:
- Backspace до пустого input
- удаление последних тегов
- повтор до полного сброса
Клавиатурная модель Tom Select формирует единый слой взаимодействия,
в котором ввод, навигация и выбор объединены в одну непрерывную систему
управления состоянием, не требующую переключения между режимами
управления.