Библиотека Focus-trap предназначена для управления фокусом внутри модальных окон, всплывающих панелей и других интерактивных компонентов интерфейса. В контексте автоматического закрытия важным становится не только удержание фокуса, но и корректное завершение работы ловушки при определённых условиях.
Focus-trap предоставляет методы и опции, которые позволяют настроить автоматическое завершение работы:
onDeactivate — коллбек, вызываемый при деактивации
ловушки. Важно использовать его для очистки ресурсов, снятия слушателей
событий и закрытия модальных окон.escapeDeactivates — булевое значение. Если
true, нажатие клавиши Escape автоматически деактивирует
ловушку.clickOutsideDeactivates — булевое значение или функция.
Позволяет закрывать модальное окно при клике вне области ловушки.
Функция предоставляет доступ к событию клика для более точной
логики.Пример настройки ловушки с автоматическим закрытием через Escape и клик вне элемента:
import { createFocusTrap } from 'focus-trap';
const modalElement = document.getElementById('modal');
const trap = createFocusTrap(modalElement, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
onDeactivate: () => {
modalElement.style.display = 'none';
console.log('Модальное окно закрыто');
}
});
trap.activate();
В некоторых случаях требуется закрывать модальные окна через
определённое время. Это реализуется сочетанием
Focus-trap и setTimeout. Таймер можно
запускать при активации ловушки, а при деактивации очищать его, чтобы
избежать неожиданных действий после закрытия.
let autoCloseTimer;
const trapWithTimer = createFocusTrap(modalElement, {
onActivate: () => {
autoCloseTimer = setTimeout(() => {
trapWithTimer.deactivate();
}, 5000); // Закрытие через 5 секунд
},
onDeactivate: () => {
clearTimeout(autoCloseTimer);
modalElement.style.display = 'none';
}
});
trapWithTimer.activate();
Ключевой момент: необходимо очищать таймер при деактивации ловушки, иначе закрытие может произойти повторно или в неподходящий момент.
Часто элементы интерфейса создаются динамически. Focus-trap поддерживает создание ловушек для таких элементов на лету. При этом важно корректно управлять жизненным циклом: создавать ловушку при открытии модального окна и деактивировать при закрытии.
function openModal(modalId) {
const modal = document.getElementById(modalId);
modal.style.display = 'block';
const dynamicTrap = createFocusTrap(modal, {
escapeDeactivates: true,
onDeactivate: () => {
modal.style.display = 'none';
}
});
dynamicTrap.activate();
}
Для автоматического закрытия также применяются внешние события:
клики, прокрутка, изменение размера окна. Focus-trap не
управляет ими напрямую, но позволяет интегрироваться через
пользовательские коллбеки и функции для
clickOutsideDeactivates.
Пример закрытия модального окна при клике вне его области:
createFocusTrap(modalElement, {
clickOutsideDeactivates: (event) => {
return !modalElement.contains(event.target);
},
onDeactivate: () => {
modalElement.style.display = 'none';
}
}).activate();
Такой подход позволяет реализовать сложную логику: закрытие при клике вне элемента, но игнорирование кликов по кнопкам управления или вложенным компонентам.
Автоматическое закрытие должно учитывать анимации появления и
скрытия. Деактивация ловушки до завершения анимации может
привести к потере фокуса или визуальной «рваности». Лучшей практикой
является запуск trap.deactivate() после окончания
CSS-анимации или события transitionend.
modalElement.addEventListener('transitionend', () => {
if (modalElement.classList.contains('closing')) {
trap.deactivate();
}
});
При автоматическом закрытии важно предусмотреть сценарии, когда
элемент уже удалён из DOM или ловушка деактивирована повторно.
Focus-trap безопасно обрабатывает повторные
деактивации, но стоит избегать прямого обращения к элементам, которых
больше нет, чтобы предотвратить ошибки типа
Cannot read property of null.
В сочетании с этими методами Focus-trap позволяет строить надёжные, управляемые модальные интерфейсы с автоматическим закрытием, сохраняя корректное поведение фокуса и предотвращая потерю управления клавиатурой.