Параметр onDeactivate

Параметр onDeactivate является одним из ключевых инструментов управления поведением фокуса в библиотеке focus-trap. Он представляет собой функцию обратного вызова, вызываемую в момент деактивации ловушки фокуса. Деактивация может происходить как вручную, так и автоматически при определённых условиях.

Назначение onDeactivate

Основное назначение onDeactivate — выполнение дополнительных действий после того, как фокус покидает ограниченную область. Чаще всего это используется для:

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

Пример базового использования:

import { createFocusTrap } from 'focus-trap';

const modal = document.getElementById('modal');
const focusTrap = createFocusTrap(modal, {
  onDeactivate: () => {
    console.log('Фокус покинул модальное окно');
  }
});

focusTrap.activate();

В этом примере onDeactivate выводит сообщение в консоль, когда ловушка фокуса деактивируется.

Поведение при деактивации

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

Важно учитывать, что:

  • Если деактивация вызвана вручную через focusTrap.deactivate(), onDeactivate будет вызван синхронно после завершения деактивации.
  • Если используется опция clickOutsideDeactivates или escapeDeactivates, onDeactivate также сработает после завершения стандартной деактивации.

Параметры функции

Функция onDeactivate не принимает аргументов напрямую, но внутри неё можно использовать внешние замыкания для доступа к элементам страницы и состоянию интерфейса. Например:

const triggerButton = document.getElementById('openModal');

const focusTrap = createFocusTrap(modal, {
  onDeactivate: () => {
    triggerButton.focus(); // возвращаем фокус на кнопку
  }
});

triggerButton.addEventListener('click', () => focusTrap.activate());

Здесь замыкание позволяет вернуть фокус на кнопку, которая открывала модальное окно.

Сочетание с checkCanFocusTrap и checkCanReturnFocus

Если используется асинхронное управление фокусом через checkCanFocusTrap или checkCanReturnFocus, onDeactivate будет вызван после завершения всех проверок и возможной анимации возврата фокуса. Это обеспечивает корректное завершение всех процедур перед выполнением финальных действий:

const focusTrap = createFocusTrap(modal, {
  checkCanReturnFocus: returnFocusElement => {
    return new Promise(resolve => {
      setTimeout(() => resolve(), 300); // имитация анимации
    });
  },
  onDeactivate: () => {
    console.log('Фокус полностью возвращен и ловушка деактивирована');
  }
});

Отличие от onActivate

onDeactivate противоположен параметру onActivate. Если onActivate управляет действиями при активации ловушки, onDeactivate отвечает за завершающие действия. Использование обоих параметров позволяет полностью контролировать жизненный цикл фокусировки:

  • onActivate — выполнение действий перед или после установки фокуса внутри контейнера.
  • onDeactivate — выполнение действий после выхода фокуса из контейнера.

Примеры практического применения

  1. Закрытие модального окна:
const focusTrap = createFocusTrap(modal, {
  onDeactivate: () => {
    modal.style.display = 'none';
  }
});
  1. Восстановление состояния интерфейса:
let wasSidebarOpen = true;

const focusTrap = createFocusTrap(sidebar, {
  onDeactivate: () => {
    if (wasSidebarOpen) sidebar.classList.add('open');
  }
});
  1. Логирование пользовательских действий:
const focusTrap = createFocusTrap(formContainer, {
  onDeactivate: () => {
    analytics.track('Form Focus Trap Deactivated');
  }
});

Рекомендации по использованию

  • Всегда использовать onDeactivate для восстановления фокуса на инициирующих элементах, чтобы не терять контекст взаимодействия пользователя.
  • Не вызывать activate внутри onDeactivate, это может привести к бесконечному циклу активации/деактивации.
  • Для сложных интерфейсов сочетать onDeactivate с асинхронными проверками через checkCanReturnFocus, чтобы учитывать анимации и динамическое изменение DOM.

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