Библиотека Tabbable предназначена для определения
элементов DOM, которые могут получать фокус с помощью клавиши Tab. Она
применяется для управления доступностью интерфейсов и упрощения
навигации для пользователей, использующих клавиатуру. В основе работы
лежит фильтрация элементов по их свойствам: tabindex,
disabled, hidden и другим атрибутам, влияющим
на возможность фокусировки.
Tabbable возвращает массив элементов в порядке их естественной табуляции. Это позволяет реализовать сложные сценарии управления фокусом без необходимости вручную проверять каждый элемент DOM.
tabbable(container) Возвращает
массив всех табулируемых элементов внутри указанного контейнера. По
умолчанию ищет элементы по всему DOM, если контейнер не указан.
import tabbable from 'tabbable';
const container = document.getElementById('form-section');
const elements = tabbable(container);
console.log(elements); // [input, button, select, ...]focusable(container) Отличается от
tabbable тем, что возвращает все элементы, которые могут
получать фокус программно, даже если они не включены в естественный
порядок табуляции.
Опции фильтрации Tabbable позволяет использовать
расширенные фильтры через атрибуты tabindex и кастомные
условия, чтобы исключать или включать элементы динамически.
Элементы с положительным tabindex получают приоритет при
навигации с помощью Tab. Tabbable учитывает этот порядок и возвращает
элементы строго в соответствии с правилами спецификации HTML:
tabindex="0" — элемент участвует в обычном порядке
табуляции.tabindex="-1" — элемент фокусируется только программно,
через element.focus().tabindex="N" (N > 0) — элемент получает приоритет
перед элементами с tabindex="0" в порядке возрастания
N.Это позволяет реализовать условную активацию элементов, когда видимость или доступность элемента меняется динамически.
Условная активация подразумевает, что элементы становятся табулируемыми только при выполнении определённых условий. Tabbable работает совместно с программной логикой для проверки состояния элементов.
Примеры условий:
Элемент видим только при открытом модальном окне
const modal = document.getElementById('modal');
const inputs = tabbable(modal);
if (modal.classList.contains('open')) {
inputs.forEach(input => input.removeAttribute('disabled'));
} else {
inputs.forEach(input => input.setAttribute('disabled', true));
}Активация по состоянию формы
Элементы могут быть активированы в зависимости от заполненности других полей:
const submitButton = document.getElementById('submit');
const requiredInput = document.getElementById('username');
requiredInput.addEventListener('input', () => {
if (requiredInput.value.trim() !== '') {
submitButton.removeAttribute('disabled');
} else {
submitButton.setAttribute('disabled', true);
}
});Динамическое управление tabindex
Позволяет полностью контролировать порядок фокуса:
const dynamicFields = document.querySelectorAll('.dynamic-field');
dynamicFields.forEach((field, index) => {
field.tabIndex = index % 2 === 0 ? 0 : -1; // фокусируются только чётные элементы
});В библиотеках вроде React или Vue Tabbable интегрируется через рефы или ссылки на DOM-элементы. Основные моменты:
useEffect или watch
позволяет динамически управлять фокусом и состоянием
disabled/tabindex.import { useEffect, useRef } from 'react';
import tabbable from 'tabbable';
function Modal({ isOpen }) {
const modalRef = useRef(null);
useEffect(() => {
if (isOpen && modalRef.current) {
const elements = tabbable(modalRef.current);
elements[0]?.focus();
}
}, [isOpen]);
return (
<div ref={modalRef} className={isOpen ? 'open' : 'closed'}>
<input type="text" />
<button>Submit</button>
</div>
);
}
tabindex для элементов,
которые должны быть доступны пользователю по Tab, если нет строгой
необходимости.aria-hidden, aria-disabled) для обеспечения
доступности.Tabbable обеспечивает точное управление навигацией по интерфейсу, позволяя реализовать гибкие сценарии условной активации и повышать доступность веб-приложений.