Библиотека Focus-trap обеспечивает управление фокусом внутри заданного DOM-элемента, предотвращая уход фокуса за пределы контейнера. Это особенно важно для модальных окон, диалогов, кастомных всплывающих меню и любых интерактивных компонентов, где необходимо удерживать пользователя внутри ограниченной области.
Установка через npm:
npm install focus-trap
Подключение в Angular:
import { createFocusTrap, FocusTrap } from 'focus-trap';
Для создания фокус-трапа используется функция
createFocusTrap, которая принимает контейнер и объект
настроек:
let trap: FocusTrap;
trap = createFocusTrap('#modal', {
escapeDeactivates: true,
clickOutsideDeactivates: true,
initialFocus: '#modal input:first-child',
fallbackFocus: '#modal',
});
Ключевые параметры:
escapeDeactivates — деактивация при нажатии
Escape.clickOutsideDeactivates — выход при клике вне
контейнера.initialFocus — элемент, который получает фокус при
активации.fallbackFocus — элемент, на который фокус вернётся,
если указанный initialFocus отсутствует.Focus-trap предоставляет следующие методы:
Пример использования с модальным окном:
openModal() {
trap.activate();
}
closeModal() {
trap.deactivate();
}
Для корректной работы внутри Angular-компонентов рекомендуется:
ngAfterViewInit.FocusTrap в компоненте, чтобы
управлять его активацией и деактивацией.import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
import { createFocusTrap, FocusTrap } from 'focus-trap';
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
})
export class ModalComponent implements AfterViewInit {
@ViewChild('modal') modalRef!: ElementRef;
private trap!: FocusTrap;
ngAfterViewInit() {
this.trap = createFocusTrap(this.modalRef.nativeElement, {
escapeDeactivates: true,
clickOutsideDeactivates: true,
});
}
open() {
this.trap.activate();
}
close() {
this.trap.deactivate();
}
}
Если в контейнер добавляются новые интерактивные элементы после
активации фокус-трапа, важно использовать опцию
allowOutsideClick и fallbackFocus, чтобы
обеспечить корректное управление фокусом даже при динамическом
контенте:
trap = createFocusTrap('#modal', {
allowOutsideClick: true,
fallbackFocus: '#modal',
});
Для динамического контента часто используют перезапуск фокус-трапа:
this.trap.deactivate();
this.trap.activate();
Focus-trap корректно обрабатывает элементы форм:
input, textarea, select,
button — автоматически включаются в порядок табуляции.initialFocus на поле
формы для удобства пользователя.trap = createFocusTrap('#form-modal', {
initialFocus: '#form-modal input[name="username"]',
});
Focus-trap можно сочетать с:
pause()
можно временно позволять пользователю взаимодействовать с элементами вне
контейнера.pause() вместо deactivate()
для временных операций, чтобы не терять состояние фокус-трапа.Focus-trap поддерживает следующие хуки:
onActivate — вызывается при активации.onDeactivate — вызывается при деактивации.onPostActivate — после активации и установки фокуса на
initialFocus.onPostDeactivate — после деактивации, позволяет
восстановить фокус на исходный элемент.Пример:
trap = createFocusTrap('#modal', {
onActivate: () => console.log('Focus trap активирован'),
onDeactivate: () => console.log('Focus trap деактивирован'),
});
Эти события полезны для логирования, анимаций и интеграции с Angular-сервисами состояния.
tabbableOptions — позволяет детально управлять тем,
какие элементы включать в порядок табуляции.returnFocusOnDeactivate — возвращает фокус на элемент,
с которого он ушёл до активации фокус-трапа.checkCanFocusTrap — асинхронная функция для проверки,
готов ли контейнер принять фокус.trap = createFocusTrap('#modal', {
returnFocusOnDeactivate: true,
tabbableOptions: { displayCheck: 'full-visible' },
});
Эти настройки обеспечивают максимальную гибкость при работе с интерактивными элементами сложной структуры.