Graceful degradation

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

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

  • Видимы на странице (display не none, visibility не hidden).
  • Не отключены (disabled не установлен).
  • Являются интерактивными (a[href], button, input, select, textarea, элементы с tabindex >= 0).

Получение фокусируемых элементов

Метод tabbable(container) возвращает массив элементов внутри указанного контейнера, которые могут получить фокус с помощью Tab. Пример использования:

import { tabbable } from 'tabbable';

const container = document.querySelector('#form');
const focusableElements = tabbable(container);

console.log(focusableElements);

Результат — массив элементов в порядке естественного табуляционного следования документа. Это особенно важно для реализации keyboard navigation и модальных окон.

Параметры и конфигурация

Библиотека поддерживает дополнительные опции:

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

Пример использования с опциями:

const elements = tabbable(container, {
  includeContainer: true,
  displayCheck: 'full' // full | non-zero-area | legacy
});

displayCheck влияет на поведение при скрытых элементах:

  • full — проверяет как display: none, так и visibility: hidden и размеры элемента.
  • non-zero-area — учитывает только элементы с ненулевой шириной и высотой.
  • legacy — старая проверка по offsetParent.

Работа с tabindex

Tabbable учитывает атрибут tabindex, позволяя правильно обрабатывать кастомные элементы. Правила:

  • tabindex="0" — элемент включается в порядок табуляции в естественном месте.
  • tabindex="-1" — элемент фокусируется только программно, в табуляции игнорируется.
  • tabindex>0 — элемент перемещается в начало последовательности, с меньшими числами — раньше.

Библиотека корректно сортирует элементы с положительным tabindex перед обычными интерактивными элементами.

Особенности работы с динамическим DOM

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

const updateFocusable = () => {
  const focusable = tabbable(document.body);
  console.log('Focusable elements:', focusable);
};

const observer = new MutationObserver(updateFocusable);
observer.observe(document.body, { childList: true, subtree: true });

Это позволяет поддерживать актуальную навигацию с клавиатуры при модальных окнах, вкладках или динамических списках.

Интеграция с модальными окнами и диалогами

Для graceful degradation в модальных окнах необходимо ограничивать фокус только элементами внутри модалки:

const modal = document.querySelector('#modal');
const focusableInModal = tabbable(modal);
focusableInModal[0].focus();

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

Обработка Shadow DOM

Tabbable умеет работать с Shadow DOM, благодаря функции getShadowRoot:

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

Это позволяет включать интерактивные элементы внутри компонентов Web Components, сохраняя правильный порядок табуляции.

Кастомизация проверки видимости

В сложных интерфейсах с анимацией или временным скрытием элементов может потребоваться свой метод проверки видимости:

const elements = tabbable(container, {
  displayCheck: el => el.offsetWidth > 0 && el.offsetHeight > 0
});

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

Суммирование особенностей

  • Определяет только видимые и интерактивные элементы.
  • Поддерживает стандартный DOM и Shadow DOM.
  • Корректно обрабатывает tabindex.
  • Позволяет гибко настраивать проверку видимости.
  • Поддерживает динамический DOM, позволяя пересчитывать фокусируемые элементы.
  • Идеально подходит для модальных окон, диалогов, выпадающих меню и компонентов с ограниченным фокусом.

Эти возможности делают Tabbable важным инструментом для обеспечения доступности и корректной работы клавиатурной навигации в современных веб-приложениях.