Библиотека Tabbable предназначена для определения всех фокусируемых элементов на странице, то есть тех, на которые пользователь может перейти с помощью клавиши Tab. Основной задачей является корректная идентификация элементов даже в сложных структурах DOM и с нестандартными атрибутами.
В контексте элементов с нестандартными атрибутами важно понимать, что
Tabbable не ограничивается только стандартными
интерактивными тегами (<a>,
<button>, <input>,
<textarea>, <select>). Любой
элемент может стать табулябельным при определённых условиях.
Функция tabbable(element) возвращает массив всех
элементов внутри element, которые считаются табулябельными.
Библиотека использует следующие критерии:
offsetWidth > 0 и
offsetHeight > 0), не скрыт через CSS
display: none или visibility: hidden.disabled не
установлен).tabindex.Ключевой момент: нестандартные атрибуты, такие как
data-focusable или role="button", могут
использоваться совместно с tabindex, чтобы сделать элемент
фокусируемым. Например:
<div data-focusable="true" tabindex="0">Фокусируемый див</div>
В этом случае Tabbable корректно идентифицирует
элемент как фокусируемый, потому что tabindex явно
указывает на возможность фокуса.
tabindextabindex — основной инструмент для управления порядком
фокусировки. Его значения:
Пример использования с нестандартными элементами:
<div role="menuitem" tabindex="0">Меню 1</div>
<div role="menuitem" tabindex="1">Меню 2</div>
<div role="menuitem" tabindex="-1">Меню 3</div>
При вызове tabbable(document.body) будут возвращены
только элементы с tabindex="0" и
tabindex="1".
Tabbable позволяет включать в выборку элементы с любыми тегами, если они удовлетворяют критериям:
tabindex ≥ 0.role="button" или role="link".hidden
атрибут или aria-hidden="true" исключают элемент).Пример с произвольными тегами и ARIA:
<section role="region" aria-label="Интерактивная секция">
<div role="button" tabindex="0">Кнопка див</div>
<span role="link" tabindex="0">Ссылка спан</span>
</section>
Библиотека корректно включит эти элементы в результат
tabbable(section).
Для работы с сложными структурами можно использовать дополнительную
фильтрацию через isTabbable:
import { tabbable, isTabbable } from 'tabbable';
const elements = document.querySelectorAll('[data-focusable]');
const focusableElements = Array.from(elements).filter(el => isTabbable(el));
Здесь isTabbable проверяет каждый элемент
индивидуально, что особенно важно для элементов с динамическими
атрибутами или скрытых элементов.
tabindex и CSS: важно,
чтобы элемент был видим. Например, opacity: 0 не исключает
элемент, но display: none — исключает.tabindex="0" или роль ARIA.tabindex без
необходимости — это нарушает предсказуемый порядок.isTabbable для проверки перед фокусировкой.display, visibility,
opacity).В React, Vue или Svelte нестандартные компоненты часто рендерятся как
<div> или <span>. Чтобы сделать их
табулябельными:
<div role="button" tabindex="0" onCl ick={handleClick}>Кнопка</div>
tabindex="0" делает элемент включенным в
последовательность Tab.role="button" обеспечивает правильную семантику и
поддержку скринридеров.Использование Tabbable с элементами, имеющими
нестандартные атрибуты, обеспечивает предсказуемую и корректную
фокусировку. Ключевыми элементами управления остаются
tabindex, видимость, и
ARIA-ролей. Комбинация этих параметров позволяет
создавать доступные и удобные интерфейсы даже с произвольными элементами
HTML.