Базовая конфигурация

Библиотека Focus-trap является инструментом для управления фокусом внутри определённых элементов DOM, что особенно важно при реализации модальных окон, дропдаунов и интерактивных виджетов. Установка возможна через npm:

npm install focus-trap

Для подключения через ES-модули используется следующий синтаксис:

import { createFocusTrap } from 'focus-trap';

Для CommonJS:

const { createFocusTrap } = require('focus-trap');

После подключения можно создавать и настраивать отдельные ловушки фокуса.


Создание ловушки фокуса

Основной метод — createFocusTrap(container, options), где container — это DOM-элемент, внутри которого нужно ограничить фокус.

Пример базовой конфигурации:

const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
  onActivate: () => modal.style.display = 'block',
  onDeactivate: () => modal.style.display = 'none',
});

Методы активации и деактивации:

focusTrap.activate();   // Включение ловушки фокуса
focusTrap.deactivate(); // Выключение ловушки фокуса

Основные опции конфигурации

initialFocus — элемент, который получит фокус при активации ловушки. Может быть:

  • Селектором CSS: '#input-name'
  • DOM-элементом: document.querySelector('#input-name')
  • Функцией, возвращающей DOM-элемент
const focusTrap = createFocusTrap(modal, {
  initialFocus: '#username'
});

fallbackFocus — элемент, который получит фокус, если initialFocus не найден или недоступен:

fallbackFocus: '#modal-close'

escapeDeactivates — разрешает или запрещает закрытие ловушки по нажатию клавиши Esc. Значения: true (по умолчанию), false или функция.

escapeDeactivates: false

clickOutsideDeactivates — отключение ловушки при клике вне контейнера. Может быть true, false или функция с логикой проверки.

clickOutsideDeactivates: (event) => !modal.contains(event.target)

returnFocusOnDeactivate — возвращает фокус на элемент, активировавший ловушку, после деактивации. По умолчанию true.


Примеры базовой конфигурации

Модальное окно с фиксированным фокусом на input

const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
  initialFocus: '#email-input',
  fallbackFocus: '#modal',
  escapeDeactivates: true,
  clickOutsideDeactivates: true,
  returnFocusOnDeactivate: true,
});

Ловушка фокуса без возможности выхода через Esc

const focusTrap = createFocusTrap(modal, {
  escapeDeactivates: false
});

Встроенные колбэки

onActivate — вызывается при активации ловушки. Часто используется для отображения модального окна или изменения стилей:

onActivate: () => modal.classList.add('active')

onDeactivate — вызывается при деактивации. Можно скрывать окно или очищать поля формы:

onDeactivate: () => {
  modal.classList.remove('active');
  modal.querySelector('form').reset();
}

checkCanFocusTrap — асинхронная функция, позволяющая задерживать активацию ловушки, пока не будет готов фокусируемый элемент:

checkCanFocusTrap: (trap) => {
  return new Promise(resolve => {
    setTimeout(() => resolve(true), 100);
  });
}

Управление несколькими ловушками

Можно создавать несколько независимых ловушек и активировать их по событию:

const trap1 = createFocusTrap(modal1);
const trap2 = createFocusTrap(modal2);

document.getElementById('open1').addEventListener('click', () => trap1.activate());
document.getElementById('open2').addEventListener('click', () => trap2.activate());

Ловушки можно деактивировать независимо или переключать между ними.


Особенности работы

  • Ловушка перехватывает все попытки перехода фокуса вне контейнера с помощью клавиши Tab и Shift+Tab.
  • Ловушка не изменяет порядок табуляции внутри контейнера.
  • Фокус автоматически возвращается на элемент, вызвавший активацию, если включена опция returnFocusOnDeactivate.
  • Асинхронная проверка элементов через checkCanFocusTrap позволяет корректно обрабатывать динамически подгружаемый контент.

Рекомендации по базовой настройке

  • Всегда задавать initialFocus или fallbackFocus, чтобы избежать потери фокуса.
  • Использовать onActivate и onDeactivate для управления видимостью элементов.
  • В сложных интерфейсах с несколькими модальными окнами создавать отдельные ловушки для каждого.
  • Отключение escapeDeactivates и clickOutsideDeactivates полезно для обязательных действий пользователя (например, подтверждение формы).

Базовая конфигурация Focus-trap обеспечивает надежный контроль фокуса, предотвращает потерю интерактивности и улучшает доступность интерфейсов.