Частые проблемы и решения

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

Базовая функция библиотеки возвращает массив элементов, которые в текущий момент считаются фокусируемыми. Эти элементы соответствуют критериям видимости, интерактивности и отсутствию атрибута tabindex="-1".

import tabbable from 'tabbable';

const container = document.querySelector('#modal');
const focusableElements = tabbable(container);
console.log(focusableElements);

Ключевые методы и параметры

  • tabbable(element, options) — основной метод.

    • element — корневой элемент, внутри которого осуществляется поиск.

    • options — объект с дополнительными настройками:

      • includeContainer — если true, сам контейнер тоже будет включён, если он фокусируемый.
      • getShadowRoot — функция для работы с Shadow DOM, возвращающая корень теневого дерева.
      • includeDisabled — позволяет включать элементы с атрибутом disabled.

Частые проблемы при использовании

1. Элементы не попадают в список фокусируемых

Наиболее распространённые причины:

  • Элемент скрыт через CSS (display: none или visibility: hidden).
  • Родительский элемент имеет display: none.
  • Используется tabindex="-1", что исключает элемент из обычного обхода клавишей Tab.
  • Элемент находится внутри Shadow DOM, а функция getShadowRoot не настроена.

Решение: проверить видимость элементов и правильность атрибутов, при работе с Shadow DOM использовать getShadowRoot.

const focusable = tabbable(container, {
  getShadowRoot: el => el.shadowRoot
});

2. Не учитываются кастомные элементы

Custom элементы, такие как <my-button>, не всегда автоматически распознаются как фокусируемые.

Решение: явно задавать tabindex="0" или использовать свойства, позволяющие библиотеке распознавать кастомный элемент как фокусируемый:

<my-button tabindex="0"></my-button>

3. Ошибки при динамическом добавлении контента

Если элементы создаются после инициализации, вызов tabbable до их добавления вернёт неполный список.

Решение: всегда вызывать функцию после вставки элементов в DOM или использовать MutationObserver для отслеживания изменений.

const observer = new MutationObserver(() => {
  const updatedList = tabbable(container);
  console.log(updatedList);
});

observer.observe(container, { childList: true, subtree: true });

4. Конфликты с disabled и aria-hidden

Элементы с disabled или aria-hidden="true" игнорируются. Иногда это создаёт неожиданные эффекты при модальных окнах и диалогах.

Решение: использовать опцию includeDisabled и корректно управлять aria-hidden для скрытия контента.

const allFocusable = tabbable(container, { includeDisabled: true });

5. Неправильная последовательность фокуса

Иногда порядок обхода клавишей Tab не соответствует визуальному порядку. Причины:

  • Неправильно проставленные tabindex (значения >0 нарушают естественный порядок).
  • Перемешивание стандартных элементов и кастомных с tabindex.

Решение: придерживаться логики tabindex = 0 для нормального обхода и избегать положительных чисел, если нужен естественный порядок.

<input type="text" tabindex="0">
<button tabindex="0">Click</button>

Советы по отладке

  1. Временно выводить результат функции tabbable(container) в консоль для проверки всех найденных элементов.
  2. Проверять родительские стили на предмет скрытия (display, visibility, opacity).
  3. Для сложных интерфейсов использовать getShadowRoot и динамическое обновление списка элементов.
  4. Использовать единый подход к tabindex и избегать конфликтов с кастомными компонентами.

Примеры практических сценариев

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

Библиотека Tabbable позволяет создать стабильный и предсказуемый фокус для веб-интерфейсов, если учитывать особенности DOM, атрибутов и Shadow DOM. Внимательное управление параметрами и понимание причин исключений делает её инструментом высокого уровня для обеспечения доступности.