Библиотека Focus-trap предназначена для управления фокусом в веб-приложениях, предотвращая случайный выход пользователя за пределы определённого интерфейсного блока, такого как модальные окна, всплывающие панели или меню. Она обеспечивает удобство навигации с клавиатуры и повышает доступность приложений, строго ограничивая область взаимодействия пользователя.
Основной объект — это трап-фокус (focus trap), который создается для конкретного DOM-элемента и управляет циклическим перемещением фокуса между интерактивными элементами внутри этого элемента.
import { createFocusTrap } from 'focus-trap';
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
initialFocus: '#first-input',
fallbackFocus: modal
});
Ключевые опции:
escapeDeactivates: разрешает деактивацию трапа при
нажатии клавиши Escape.clickOutsideDeactivates: позволяет закрывать трап при
клике вне элемента.initialFocus: задает элемент, на который будет
установлен фокус при активации трапа.fallbackFocus: элемент, который получает фокус, если
initialFocus не найден.Создание нового трапа каждый раз при открытии модального окна может приводить к лишним расходам памяти и усложнять управление состояниями. Переиспользование экземпляров позволяет создавать трап один раз и активировать его многократно.
const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
initialFocus: '#first-input'
});
function openModal() {
modal.style.display = 'block';
focusTrap.activate();
}
function closeModal() {
focusTrap.deactivate();
modal.style.display = 'none';
}
В данном случае один экземпляр
focusTrap используется каждый раз при открытии модального
окна. Деактивация освобождает управление фокусом, но сам объект остаётся
доступным для повторной активации.
При переиспользовании экземпляров важно управлять динамическими
элементами внутри контейнера. Если интерактивные элементы добавляются
или удаляются, трап автоматически корректирует порядок фокуса, но можно
задать новый initialFocus при активации:
function openModalWithDynamicFocus(selector) {
focusTrap.setInitialFocus(selector);
focusTrap.activate();
}
Метод setInitialFocus позволяет изменить элемент, на
который будет установлен фокус, без создания нового экземпляра
трапа.
Для интерфейсов с несколькими модальными окнами имеет смысл создавать отдельные экземпляры трапа для каждого окна, но при этом активировать только один трап в любой момент. Это предотвращает конфликт фокуса и сохраняет доступность:
const modalA = createFocusTrap(document.getElementById('modalA'));
const modalB = createFocusTrap(document.getElementById('modalB'));
function openModalA() {
modalB.deactivate();
modalA.activate();
}
function openModalB() {
modalA.deactivate();
modalB.activate();
}
Вариант с переиспользованием одного трапа на разные контейнеры
возможен, но требует корректной перенастройки
container:
focusTrap.updateContainer(newContainer);
focusTrap.activate();
onActivate и
onDeactivate, чтобы выполнять определённые действия без
создания нового экземпляра.updateContainer и setInitialFocus.onActivate и onDeactivate
упрощает интеграцию с анимациями и сторонними библиотеками.Переиспользование экземпляров Focus-trap снижает накладные расходы и повышает производительность, сохраняя при этом строгий контроль за фокусом и доступностью интерфейсов.