deactivate()

Метод deactivate() используется для отключения активной ловушки фокуса. После вызова этого метода библиотека прекращает перехватывать навигацию по элементам интерфейса и возвращает поведение фокуса к стандартной логике браузера.

Focus Trap применяет механизм ограничения фокуса внутри заданного контейнера: пользователь может перемещаться между интерактивными элементами только внутри этой области. Такое поведение часто используется в модальных окнах, диалогах, выпадающих панелях и других элементах интерфейса, которые должны временно изолировать взаимодействие.

deactivate() завершает этот режим.


Общий принцип работы деактивации

Во время активации ловушки фокуса библиотека выполняет несколько действий:

  • отслеживает события клавиатуры (Tab, Shift + Tab);
  • контролирует изменение фокуса (focusin);
  • предотвращает переход фокуса за пределы контейнера;
  • сохраняет элемент, который имел фокус до активации.

Метод deactivate() отменяет эти механизмы:

  1. удаляет обработчики событий;
  2. отключает внутренние проверки перехода фокуса;
  3. освобождает заблокированные элементы;
  4. при необходимости возвращает фокус на предыдущий элемент.

Таким образом интерфейс возвращается в обычное состояние.


Базовый синтаксис

trap.deactivate();

Где trap — экземпляр ловушки фокуса, созданный функцией createFocusTrap.

Пример создания и деактивации:

import { createFocusTrap } from 'focus-trap';

const modal = document.querySelector('#modal');

const trap = createFocusTrap(modal);

trap.activate();

// позже
trap.deactivate();

После выполнения deactivate() пользователь снова может перемещать фокус по всей странице.


Возврат фокуса после деактивации

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

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

Типичный сценарий:

  1. пользователь нажимает кнопку открытия модального окна;
  2. активируется ловушка фокуса внутри модального окна;
  3. после закрытия модального окна вызывается deactivate();
  4. фокус возвращается на кнопку открытия.

Пример:

const button = document.querySelector('#open-modal');
const modal = document.querySelector('#modal');

const trap = createFocusTrap(modal);

button.addEventListener('click', () => {
  trap.activate();
});

document.querySelector('#close').addEventListener('click', () => {
  trap.deactivate();
});

После закрытия окна фокус снова окажется на #open-modal.


Параметры метода

Метод deactivate() может принимать объект параметров:

trap.deactivate(options);

Основные параметры:

Параметр Назначение
returnFocus управляет возвратом фокуса
checkCanReturnFocus асинхронная проверка перед возвратом
onDeactivate колбэк при деактивации

Параметр returnFocus

Определяет, нужно ли возвращать фокус на предыдущий элемент.

trap.deactivate({
  returnFocus: false
});

Если значение false, библиотека не будет восстанавливать фокус. Это полезно в случаях, когда:

  • интерфейс полностью изменился;
  • элемент-источник был удалён из DOM;
  • требуется вручную назначить фокус другому элементу.

Параметр checkCanReturnFocus

Этот параметр используется, если возвращение фокуса должно произойти после выполнения асинхронной операции.

trap.deactivate({
  checkCanReturnFocus: (trigger) => {
    return new Promise((resolve) => {
      setTimeout(resolve, 300);
    });
  }
});

Аргумент trigger содержит элемент, который имел фокус до активации ловушки.

Частые сценарии использования:

  • ожидание окончания CSS-анимации закрытия;
  • ожидание удаления модального окна;
  • ожидание завершения перехода интерфейса.

Параметр onDeactivate

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

trap.deactivate({
  onDeactivate: () => {
    console.log('Focus trap отключена');
  }
});

Этот колбэк вызывается сразу после завершения деактивации.

Применяется для:

  • синхронизации состояния интерфейса;
  • очистки ресурсов;
  • логирования событий.

Поведение обработчиков событий

Во время активации Focus Trap регистрирует несколько слушателей:

  • keydown
  • focusin
  • mousedown
  • touchstart
  • click

Метод deactivate() удаляет все эти обработчики. Это предотвращает:

  • перехват клавиши Tab;
  • принудительный возврат фокуса;
  • блокировку кликов вне контейнера.

После деактивации поведение страницы становится полностью стандартным.


Взаимодействие с несколькими ловушками

В сложных интерфейсах возможно существование нескольких ловушек фокуса. Например:

  • модальное окно;
  • всплывающее меню;
  • вложенный диалог.

Когда активируется новая ловушка, предыдущая может быть автоматически приостановлена.

При вызове deactivate() происходит одно из двух действий:

  • ловушка полностью отключается;
  • активируется предыдущая ловушка в стеке.

Пример:

modalTrap.activate();
nestedDialogTrap.activate();

nestedDialogTrap.deactivate();

После деактивации вложенного диалога фокус снова будет ограничен модальным окном.


Типичный сценарий использования

Чаще всего deactivate() применяется при закрытии интерфейсных компонентов.

Модальное окно

const trap = createFocusTrap('#modal');

function openModal() {
  modal.classList.add('open');
  trap.activate();
}

function closeModal() {
  modal.classList.remove('open');
  trap.deactivate();
}

Закрытие по клавише Escape

document.addEventListener('keydown', (event) => {
  if (event.key === 'Escape') {
    trap.deactivate();
  }
});

Закрытие по клику вне области

document.addEventListener('click', (event) => {
  if (!modal.contains(event.target)) {
    trap.deactivate();
  }
});

Влияние на доступность интерфейса

Корректная деактивация ловушки фокуса играет важную роль в обеспечении доступности:

  • возвращается логический порядок навигации;
  • восстанавливается контекст пользователя;
  • экранные читатели корректно продолжают взаимодействие.

Если ловушка не деактивируется корректно, могут возникнуть проблемы:

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

Поэтому deactivate() должен вызываться всегда при закрытии компонентов, использующих Focus Trap.


Внутренняя логика выполнения

Процесс деактивации включает несколько этапов:

  1. Проверка состояния ловушки.
  2. Отмена активных слушателей событий.
  3. Снятие ограничений перемещения фокуса.
  4. Вызов пользовательских колбэков.
  5. При необходимости — возврат фокуса.

Схематически:

activate()
   ↓
focus trapping
   ↓
deactivate()
   ↓
remove listeners
restore focus

Такой механизм обеспечивает безопасное завершение работы ловушки без конфликтов с другими компонентами интерфейса.


Особенности при динамическом DOM

Если элемент, который должен получить фокус после деактивации, удалён из DOM, библиотека пытается:

  1. найти ближайший доступный элемент;
  2. установить фокус на document.body.

Поэтому при динамических интерфейсах иногда отключают автоматическое возвращение фокуса:

trap.deactivate({
  returnFocus: false
});

После этого фокус назначается вручную.


Связь с другими методами

Метод deactivate() работает совместно с несколькими ключевыми методами Focus Trap.

activate() Запускает ловушку фокуса.

pause() Временно приостанавливает ловушку без полного отключения.

unpause() Возобновляет работу после паузы.

Разница между ними:

Метод Эффект
pause() временная остановка
unpause() восстановление
deactivate() полное завершение

deactivate() используется, когда ловушка больше не требуется.


Практические рекомендации

Синхронизация с анимациями

Часто модальные окна закрываются с анимацией. В таких случаях деактивацию выполняют после завершения анимации:

modal.addEventListener('animationend', () => {
  trap.deactivate();
});

Проверка существования элемента

Перед возвратом фокуса важно убедиться, что исходный элемент не был удалён.

Единая точка управления

В крупных приложениях логика открытия и закрытия интерфейсов централизуется в одном модуле, который отвечает за вызовы activate() и deactivate().


Метод deactivate() является ключевым элементом жизненного цикла Focus Trap. Он завершает изоляцию фокуса, восстанавливает стандартную навигацию и обеспечивает корректное взаимодействие пользователя с остальной частью интерфейса.