Сортировка и фильтрация

Библиотека Tabbable предназначена для идентификации элементов в DOM, на которые пользователь может перемещаться с помощью клавиши Tab. Она используется в сценариях, где важно управление фокусом, например, при реализации модальных окон, кастомных компонентов формы и интерактивных виджетов.

Ключевой принцип работы: Tabbable не изменяет DOM и не управляет фокусом напрямую. Она анализирует элементы, учитывает их свойства и возвращает список элементов, которые могут быть доступны пользователю через клавиатуру.


Получение tabbable-элементов

Основная функция библиотеки — tabbable(container, options):

import { tabbable } from 'tabbable';

const elements = tabbable(document.body);
  • container — корневой элемент, внутри которого производится поиск.

  • options — объект с настройками фильтрации:

    • includeContainer (boolean) — включать ли сам контейнер в результат, если он tabbable.
    • getShadowRoot (function) — функция для обхода Shadow DOM.

Функция возвращает массив элементов, упорядоченных так, как они будут перебираться при нажатии Tab.


Критерии tabbable-элемента

Tabbable использует строгие правила для определения доступности элемента:

  1. Видимость: элемент должен быть видимым (displaynone, visibilityhidden).

  2. Фокусируемость: элемент поддерживает фокус:

    • <input>, <select>, <textarea>, <button>, <a href>
    • элементы с атрибутом tabindex ≥ 0
  3. Состояние: элементы не должны быть отключены (disabled) или иметь родительский блок с aria-hidden="true".


Сортировка элементов

Порядок в массиве, возвращаемом Tabbable, соответствует естественному порядку табуляции в браузере:

  1. Элементы с tabindex = 0, расположенные по DOM-структуре сверху вниз.
  2. Элементы с tabindex > 0, упорядоченные по возрастанию значения tabindex.
  3. Shadow DOM элементы сортируются относительно их слота и родительских элементов.

Важно учитывать, что браузеры обрабатывают tabindex по-разному, но Tabbable обеспечивает единообразие, вычисляя порядок программно.

// Пример сортировки по tabIndex вручную
const sorted = tabbable(document.body).sort((a, b) => {
  return (a.tabIndex || 0) - (b.tabIndex || 0);
});

Фильтрация элементов

Для точного управления можно использовать функции фильтрации:

const focusableInputs = tabbable(document.body).filter(el => el.tagName === 'INPUT');

Опции фильтрации через options:

  • includeDisabled — включать элементы с disabled.
  • includeOnlyFocusable — исключить элементы, которые хоть и tabbable, но не могут получать фокус программно.

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


Обход Shadow DOM

Tabbable поддерживает Shadow DOM, что важно для современных веб-компонентов.

const elements = tabbable(document.body, {
  getShadowRoot: el => el.shadowRoot
});
  • Функция getShadowRoot возвращает shadowRoot для каждого элемента, если он существует.
  • Элементы внутри Shadow DOM включаются в общий список с сохранением порядка табуляции.

Практические примеры

Модальное окно:

const modal = document.querySelector('.modal');
const focusable = tabbable(modal);

// Устанавливаем фокус на первый элемент
focusable[0].focus();

// Перемещение фокуса по циклу внутри модального окна
modal.addEventListener('keydown', e => {
  if (e.key === 'Tab') {
    const index = focusable.indexOf(document.activeElement);
    const nextIndex = e.shiftKey ? index - 1 : index + 1;
    e.preventDefault();
    focusable[(nextIndex + focusable.length) % focusable.length].focus();
  }
});

Фильтрация по типу элемента:

const onlyButt ons = tabbable(document.body).filter(el => el.tagName === 'BUTTON');

Рекомендации по использованию

  • Всегда проверять элементы на видимость и состояние disabled.
  • Использовать tabindex > 0 только при необходимости, чтобы избежать нарушения естественного порядка табуляции.
  • Для компонентов с Shadow DOM применять getShadowRoot, чтобы корректно учитывать вложенные tabbable-элементы.
  • Фильтры позволяют выделять отдельные типы элементов или создавать ограниченные зоны фокусировки, что повышает доступность интерфейса.

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