Библиотека Focus-trap предназначена для управления фокусом внутри определённого контейнера на странице. Она предотвращает случайное выходное перемещение фокуса за пределы модального окна, панели или любого другого интерактивного блока. Это особенно важно для доступности (accessibility), когда пользователи взаимодействуют с интерфейсом с помощью клавиатуры или вспомогательных технологий.
Focus-trap создаёт «ловушку фокуса», которая:
Для работы с библиотекой необходим элемент DOM, внутри которого будет
ограничен фокус. Основной метод — createFocusTrap:
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
allowOutsideClick: true
});
Параметры:
Активация и деактивация осуществляется методами:
focusTrap.activate();
focusTrap.deactivate();
Хотя основное управление фокусом происходит через Tab и Shift+Tab, Focus-trap позволяет интегрировать управление стрелками. Это полезно для меню, табов и сложных интерфейсов с сеткой элементов.
Для этого требуется:
element.focus().Пример для горизонтального меню:
const menuItems = Array.from(modal.querySelectorAll('button, [tabindex]:not([tabindex="-1"])'));
modal.addEventListener('keydown', (e) => {
const index = menuItems.indexOf(document.activeElement);
if (e.key === 'ArrowRight') {
e.preventDefault();
const nextIndex = (index + 1) % menuItems.length;
menuItems[nextIndex].focus();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
const prevIndex = (index - 1 + menuItems.length) % menuItems.length;
menuItems[prevIndex].focus();
}
});
Важные моменты:
menuItems должен содержать только
интерактивные элементы, доступные для фокуса.preventDefault() предотвращает
стандартное поведение браузера и обеспечивает предсказуемость
навигации.В сложных интерфейсах с сеткой (например, таблицы, галереи) удобно комбинировать Tab и стрелки:
modal.addEventListener('keydown', (e) => {
const index = gridItems.indexOf(document.activeElement);
if (e.key === 'ArrowDown') {
e.preventDefault();
const nextIndex = (index + columns) % gridItems.length;
gridItems[nextIndex].focus();
} else if (e.key === 'ArrowUp') {
e.preventDefault();
const prevIndex = (index - columns + gridItems.length) % gridItems.length;
gridItems[prevIndex].focus();
}
});
Focus-trap поддерживает хуки для дополнительного контроля:
Пример:
const focusTrap = createFocusTrap(modal, {
onActivate: () => console.log('Ловушка активирована'),
onDeactivate: () => console.log('Ловушка деактивирована'),
checkCanFocusTrap: () => new Promise(resolve => {
setTimeout(() => resolve(true), 100);
})
});
Focus-trap обеспечивает безопасное и предсказуемое управление фокусом, позволяя реализовать как стандартную навигацию Tab, так и продвинутую навигацию стрелками, соответствующую современным требованиям доступности и UX.