Невозможность деактивации диалога

Библиотека Focus-trap предназначена для управления фокусом внутри определённой области DOM, чаще всего модальных окон, всплывающих панелей или диалогов. Она гарантирует, что пользовательский фокус не покидает контейнер до явного выхода, предотвращая случайное взаимодействие с элементами вне области. Основная цель — обеспечить доступность интерфейса, соответствующую стандартам WAI-ARIA.

Фокусировка управляется через трап (trap), который перехватывает нажатия клавиш, переход по табуляции (Tab и Shift+Tab) и программно управляет элементами DOM. Библиотека предоставляет методы для активации и деактивации трапа, а также настраиваемые события при выходе из зоны фокуса.


Создание и активация трапа

Трап создается с помощью функции createFocusTrap, куда передается контейнер и набор опций:

import { createFocusTrap } from 'focus-trap';

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

focusTrap.activate();

Ключевые моменты опций:

  • escapeDeactivates: при значении true клавиша Escape снимает фокус с контейнера.
  • clickOutsideDeactivates: контролирует возможность деактивации при клике вне зоны.
  • initialFocus: задает элемент, который получит фокус при активации трапа.

Невозможность деактивации

Сценарии, когда необходимо заблокировать возможность выхода из модального окна, реализуются через комбинацию опций:

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

В этом случае ни клавиша Escape, ни клики за пределами модального окна не приведут к деактивации трапа. Фокус остаётся строго внутри контейнера до явного вызова метода deactivate().

Особенности поведения:

  • Пользователь не сможет переключиться на элементы страницы через Tab или мышь вне модального окна.
  • Всплывающие события, такие как blur или потеря фокуса, автоматически возвращают фокус внутрь контейнера.
  • При использовании returnFocusOnDeactivate: true фокус вернется к элементу, который был активен перед активацией трапа, но только после явного вызова deactivate().

Программная блокировка деактивации

Для сложных интерфейсов возможно динамически управлять деактивацией:

const focusTrap = createFocusTrap(modal, {
  escapeDeactivates: false,
  clickOutsideDeactivates: false,
  onDeactivate: () => console.log('Попытка деактивации'),
});

focusTrap.activate();

// Программно попытка деактивации
focusTrap.deactivate({ returnFocus: false });

Даже при вызове deactivate() можно контролировать возврат фокуса через параметр returnFocus. В ситуациях, где необходима абсолютная блокировка, вызовы деактивации можно перехватывать и отменять через пользовательские колбэки.


Интеграция с динамическим контентом

Focus-trap корректно работает с элементами, которые добавляются в DOM после активации:

const dynamicInput = document.createElement('input');
dynamicInput.id = 'dynamic';
modal.appendChild(dynamicInput);

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


Работа с множественными трапами

В интерфейсах с несколькими модальными окнами важно соблюдать стек трапов. Например, если одно окно открыто над другим:

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

trap1.activate();
trap2.activate(); // Временно блокирует trap1

При закрытии верхнего трапа фокус возвращается в предыдущий. Если верхний трап настроен с escapeDeactivates: false, выход невозможен до явного вызова deactivate().


Практические советы по блокировке выхода

  1. Использовать escapeDeactivates: false и clickOutsideDeactivates: false для полного контроля.
  2. Перехватывать колбэки onDeactivate для логирования или отмены случайных деактиваций.
  3. Управлять возвращением фокуса через returnFocusOnDeactivate или вручную через document.activeElement.
  4. Проверять доступность динамически созданных элементов внутри контейнера, чтобы трап охватывал все интерактивные элементы.
  5. Не полагаться на браузерные события blur для предотвращения выхода — библиотека сама корректно обрабатывает фокус.

Эта архитектура делает Focus-trap надёжным инструментом для создания интерфейсов, где невозможность деактивации является требованием безопасности, UX или строгой последовательности действий пользователя.