Тестирование доступности

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

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

  • Элементы <a> с атрибутом href
  • Элементы <button>, <input>, <textarea>, <select>
  • Любые элементы с атрибутом tabindex, кроме отрицательного (tabindex="-1")
  • Элементы с видимым контентом и стилем display: none или visibility: hidden исключаются

Работа с функцией tabbable()

Функция имеет следующий синтаксис:

import { tabbable } from 'tabbable';

const focusableElements = tabbable(document.body);

Результатом является массив DOM-элементов, которые можно последовательно обойти с помощью Tab. Порядок элементов в массиве соответствует визуальному порядку на странице, с учётом стандартного потока документа и атрибутов tabindex.

Примеры фильтрации:

  • Элементы с tabindex="-1" игнорируются.
  • Скритые элементы (display: none, visibility: hidden) исключаются.
  • Динамически добавленные элементы могут быть обнаружены при повторном вызове tabbable().

Особенности определения видимости

Tabbable проверяет не только стиль самого элемента, но и его родителей. Элемент считается невидимым, если он находится внутри контейнера с display: none или visibility: hidden. Это обеспечивает точное соответствие поведения клавиши Tab в браузерах.

const container = document.getElementById('modal');
const focusable = tabbable(container);
console.log(focusable); // только видимые и фокусируемые элементы внутри модального окна

Управление порядком фокусировки

Порядок табуляции регулируется с помощью атрибута tabindex. Элементы с положительными значениями tabindex получают приоритет перед элементами с tabindex="0" и стандартными элементами формы. Элементы с одинаковым положительным tabindex фокусируются в порядке их появления в DOM.

<input type="text" tabindex="2">
<input type="text" tabindex="1">
<button>Кнопка</button>

При использовании tabbable() первый в массиве будет элемент с tabindex="1", затем tabindex="2", и только потом стандартные фокусируемые элементы.

Использование в тестах доступности

Tabbable применяется для проверки доступности интерфейсов:

  1. Модальные окна: убедиться, что фокус остаётся внутри модального окна и не уходит на элементы под ним.
  2. Диалоговые элементы: проверить, что все интерактивные элементы доступны по Tab.
  3. Кастомные компоненты: определить, корректно ли установлены tabindex для кнопок, списков и панелей навигации.

Пример теста на Jest:

import { tabbable } from 'tabbable';

test('фокус внутри модального окна', () => {
  document.body.innerHTML = `
    <div id="modal">
      <button>Закрыть</button>
      <input type="text" />
    </div>
  `;
  const modal = document.getElementById('modal');
  const focusable = tabbable(modal);
  expect(focusable.length).toBe(2);
  expect(focusable[0].textContent).toBe('Закрыть');
});

Интеграция с фреймворками

В React, Vue и других фреймворках Tabbable удобно использовать для контроля фокуса после рендеринга компонентов:

useEffect(() => {
  const firstFocusable = tabbable(modalRef.current)[0];
  if (firstFocusable) firstFocusable.focus();
}, []);

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

Расширенные возможности

  • getTabbableCandidates(root): возвращает все потенциально фокусируемые элементы без фильтрации по видимости.
  • isTabbable(element): проверяет, можно ли элементу получать фокус через Tab.
  • Совместимость с Shadow DOM: библиотека корректно обрабатывает слоты и вложенные shadow root.

Советы по использованию

  • Включать Tabbable в процессы тестирования компонентов для автоматической проверки доступности.
  • Использовать tabbable() для управления фокусом при динамическом создании интерфейсов.
  • Проверять порядок табуляции после добавления новых элементов или изменения DOM, чтобы не нарушать ожидаемое поведение пользователя с клавиатурой.

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