Логирование и отладка

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

Основной экспорт библиотеки — функция tabbable, которая принимает DOM-элемент или документ и возвращает массив элементов, доступных для табуляции.

import { tabbable } from 'tabbable';

const focusableElements = tabbable(document.body);
console.log(focusableElements);

Результатом является отсортированный список элементов, соответствующий порядку, в котором пользователь будет переходить по ним с помощью клавиши Tab.


Ключевые методы и функции

tabbable(node, options)

  • node — контейнер, внутри которого производится поиск фокусируемых элементов.

  • options — объект настроек:

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

Возвращает массив элементов, доступных для табуляции. Элементы сортируются по логическому DOM-порядку и учитывают атрибуты tabindex и disabled.

isTabbable(element)

Проверяет, может ли конкретный элемент получать фокус с помощью Tab. Возвращает true или false.

import { isTabbable } from 'tabbable';

const button = document.querySelector('button');
console.log(isTabbable(button)); // true или false

focusable(element)

Определяет, может ли элемент получить фокус вообще (не только через Tab, но и программно). Отличается от isTabbable тем, что учитывает все способы фокусировки, включая скриптовые вызовы element.focus().


Обработка нестандартных элементов

Библиотека корректно работает с элементами:

  • SVG и custom elements — поддерживается фокусировка через tabindex.
  • Shadow DOM — через опцию getShadowRoot, позволяющую рекурсивно находить фокусируемые элементы внутри теневого дерева.
  • Скрытые элементы — элементы с display: none или visibility: hidden игнорируются, что предотвращает случайное включение невидимых кнопок в порядок табуляции.

Пример рекурсивного поиска в Shadow DOM:

const focusableInShadow = tabbable(document.querySelector('my-component'), {
  getShadowRoot: el => el.shadowRoot
});

Порядок фокусировки и tabindex

Элементы с tabindex управляют порядком перемещения фокуса:

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

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


Отладка и логирование

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

Пример простого логирования:

const elements = tabbable(document.body);
elements.forEach((el, index) => {
  console.log(`${index + 1}: <${el.tagName.toLowerCase()}>`, el);
});

Дополнительные практики для отладки:

  • Использование CSS для временной визуализации фокусируемых элементов:
.tab-debug:focus {
  outline: 2px solid red !important;
}
  • Добавление динамических классов через JavaScript при вычислении tabbable элементов:
tabbable(document.body).forEach(el => el.classList.add('tab-debug'));

Это позволяет визуально проверять, совпадает ли порядок элементов с ожидаемым.


Интеграция с тестами

Unit-тесты и e2e-тесты можно строить на базе Tabbable, проверяя доступность ключевых интерфейсных компонентов:

import { tabbable } from 'tabbable';
import { expect } from 'chai';

const focusableElements = tabbable(document.querySelector('#form'));
expect(focusableElements[0].tagName.toLowerCase()).to.equal('input');

Использование Tabbable в тестах помогает автоматизировать проверку доступности и выявлять элементы с неправильным tabindex.


Практические рекомендации

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

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