Создание собственных предустановок

Библиотека Focus-trap предназначена для управления фокусом внутри заданного контейнера. Она гарантирует, что пользовательский фокус не выйдет за пределы элемента, пока активен «ловушка фокуса». Это особенно важно для модальных окон, всплывающих меню и других интерактивных компонентов, где фокус должен оставаться внутри определённой области.

Фокусировка осуществляется через контроль последовательности элементов с атрибутами tabindex, <button>, <input>, <a> и других интерактивных тегов. Focus-trap перехватывает события клавиш Tab и Shift+Tab, создавая циклическую навигацию внутри контейнера.


Создание предустановок

Предустановка (preset) в Focus-trap позволяет заранее определить настройки поведения ловушки фокуса, которые можно многократно использовать для разных элементов. Это упрощает код и повышает читаемость, особенно когда проект содержит несколько модальных компонентов с одинаковыми правилами фокусировки.

Для создания предустановки используется объект конфигурации:

import { createFocusTrap } from 'focus-trap';

const modalFocusTrapConfig = {
  escapeDeactivates: true,      // деактивация ловушки при нажатии Escape
  clickOutsideDeactivates: true, // закрытие при клике вне контейнера
  returnFocusOnDeactivate: true, // возврат фокуса к исходному элементу
  initialFocus: '#firstInput',   // фокус на конкретный элемент при активации
  fallbackFocus: '#modal',        // элемент для фокуса, если initialFocus отсутствует
  allowOutsideClick: false        // запрет клика вне контейнера без деактивации
};

После создания конфигурации можно использовать её для любого контейнера:

const modalTrap = createFocusTrap('#modal', modalFocusTrapConfig);
modalTrap.activate();

Ключевые опции конфигурации

  • escapeDeactivates – логическое значение, определяющее возможность деактивации ловушки клавишей Escape. Полезно для модальных окон, которые должны закрываться по Esc.
  • clickOutsideDeactivates – позволяет отключить ловушку при клике за пределами контейнера. Можно передать функцию для условной деактивации.
  • returnFocusOnDeactivate – возвращает фокус на элемент, который был активен до активации ловушки. Предотвращает потерю контекста навигации.
  • initialFocus – селектор или функция, возвращающая элемент, на который будет установлен фокус при активации ловушки.
  • fallbackFocus – элемент, на который фокус установится, если initialFocus не найден или недоступен.
  • allowOutsideClick – контролирует возможность клика вне контейнера без деактивации. Можно использовать функцию, чтобы разрешить клик на определённые элементы.

Создание собственных функций предустановок

Focus-trap позволяет создавать не просто объекты конфигурации, а функции предустановок, которые возвращают готовую конфигурацию в зависимости от параметров. Это удобно для динамических модальных окон или компонентов с различными условиями активации.

Пример функции предустановки:

function createModalPreset(focusId, closeOnClick = true) {
  return {
    escapeDeactivates: true,
    clickOutsideDeactivates: closeOnClick,
    returnFocusOnDeactivate: true,
    initialFocus: `#${focusId}`,
    fallbackFocus: '#modal'
  };
}

// Использование
const modalTrap = createFocusTrap('#modal', createModalPreset('usernameInput', false));
modalTrap.activate();

Такой подход делает код масштабируемым: при изменении логики модального окна достаточно изменить одну функцию, а не каждый объект конфигурации.


Комбинирование предустановок

Можно создавать базовую предустановку и расширять её с помощью spread-оператора или Object.assign, добавляя уникальные опции для конкретных случаев:

const basePreset = {
  escapeDeactivates: true,
  returnFocusOnDeactivate: true,
  fallbackFocus: '#modal'
};

const formModalPreset = {
  ...basePreset,
  initialFocus: '#formInput',
  clickOutsideDeactivates: false
};

const settingsModalPreset = {
  ...basePreset,
  initialFocus: '#settingsButton',
  clickOutsideDeactivates: true
};

Такой подход позволяет централизованно управлять поведением ловушек фокуса в проекте.


Динамическая активация и деактивация

Focus-trap предоставляет методы activate() и deactivate(). Предустановки влияют только на конфигурацию, но управление активацией всегда остаётся явным:

const trap = createFocusTrap('#modal', formModalPreset);

// Открытие модального окна
document.querySelector('#openModal').addEventListener('click', () => trap.activate());

// Закрытие модального окна
document.querySelector('#closeModal').addEventListener('click', () => trap.deactivate());

Для сложных интерфейсов можно хранить массив предустановок и применять их по типу модального окна или контекста.


Важные рекомендации при создании предустановок

  • Использовать fallbackFocus для предотвращения потери фокуса в случае ошибок селектора.
  • Централизованно хранить предустановки, чтобы избежать дублирования кода.
  • При работе с динамическим контентом проверять существование initialFocus до активации.
  • Ограничивать использование allowOutsideClick только для случаев, когда это действительно необходимо.
  • Для сложных приложений создавать функции-предустановки вместо жестко закодированных объектов, чтобы легко менять поведение.

Эта структура позволяет создавать масштабируемые и управляемые ловушки фокуса в проектах любой сложности, обеспечивая согласованное поведение модальных компонентов и интерактивных областей.