Навигация с клавиатуры

Навигация с клавиатуры в 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) не перехватываются
  • системные комбинации имеют приоритет
  • события обрабатываются только при активном фокусе компонента

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

  1. проверка фокуса
  2. определение типа состояния (open/closed/input)
  3. обработка keydown
  4. предотвращение default при необходимости
  5. обновление UI

Особенности поведения в разных режимах

В single-select:

  • стрелки управляют одной активной опцией
  • Enter заменяет текущее значение
  • Backspace не влияет на список выбранных

В multi-select:

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

В режиме создания новых значений:

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

Производительность при активной навигации

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

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

Навигация стрелками не вызывает перерасчёт всего списка, изменяется только состояние подсветки.


Типичные сценарии взаимодействия

Сценарий последовательного выбора:

  • открытие списка через ArrowDown
  • перемещение по опциям
  • Enter для выбора
  • повтор навигации без закрытия списка

Сценарий быстрого поиска:

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

Сценарий очистки:

  • Backspace до пустого input
  • удаление последних тегов
  • повтор до полного сброса

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