useDismiss хук

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

Основные возможности

  • Закрытие по клику вне элемента (outsideClick) Позволяет автоматически закрывать всплывающее окно, если пользователь кликает за пределами таргетного элемента. Пример использования:

    import { useDismiss } from '@floating-ui/react';
    
    const dismiss = useDismiss({
      outsidePress: true,
    });
    
    <div {...dismiss}>
      Всплывающее окно
    </div>

    В этом примере любая попытка клика за пределами элемента <div> инициирует событие закрытия.

  • Закрытие по клавише Escape (escapeKey) Обеспечивает возможность закрытия окна при нажатии клавиши Escape. Это особенно важно для доступности интерфейса.

    const dismiss = useDismiss({
      escapeKey: true,
    });
  • Закрытие при потере фокуса (referencePress) Если всплывающий элемент связан с целевым элементом (например, кнопкой открытия), можно настроить закрытие при взаимодействии с этим элементом.

Конфигурация хука

Хук принимает объект с настройками:

interface UseDismissProps {
  outsidePress?: boolean; // закрытие по клику вне элемента
  escapeKey?: boolean;    // закрытие по Escape
  referencePress?: boolean; // закрытие при взаимодействии с reference
  disabled?: boolean;     // временное отключение хука
  onDismiss?: () => void; // callback при закрытии
}

Ключевые параметры:

  • outsidePress — если true, добавляется слушатель кликов по документу для проверки, произошёл ли клик вне элемента.
  • escapeKey — при true добавляется обработчик нажатия клавиши Escape.
  • referencePress — позволяет реагировать на клики по привязанному элементу.
  • disabled — временно отключает хук, не вызывая закрытие.
  • onDismiss — функция обратного вызова, вызываемая при срабатывании любого механизма закрытия.

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

import { useFloating, useDismiss } from '@floating-ui/react';

function Tooltip({ isOpen, onClose }) {
  const { x, y, reference, floating } = useFloating();
  const dismiss = useDismiss({
    escapeKey: true,
    outsidePress: true,
    onDismiss: onClose,
  });

  return (
    <>
      <button ref={reference}>Наведите на меня</button>
      {isOpen && (
        <div
          ref={floating}
          style={{ position: 'absolute', top: y ?? 0, left: x ?? 0 }}
          {...dismiss}
        >
          Всплывающая подсказка
        </div>
      )}
    </>
  );
}

В этом примере комбинация useFloating и useDismiss обеспечивает:

  • Автоматическое позиционирование всплывающего элемента.
  • Закрытие при клике вне тултипа.
  • Закрытие при нажатии Escape.
  • Обработку через onDismiss для синхронизации состояния в родительском компоненте.

Важные особенности

  1. Композиция хуков useDismiss можно комбинировать с другими хуками Floating UI, такими как useRole или useInteractions. Это позволяет централизованно управлять поведением всплывающего элемента, включая фокусировку и обработку кликов.

  2. Поддержка отключения Временное отключение через disabled полезно, когда требуется динамически блокировать автоматическое закрытие (например, при анимации).

  3. Контекстная обработка событий Хук корректно работает с вложенными элементами и предотвращает закрытие при взаимодействии с внутренними дочерними элементами, если они находятся в пределах привязанного DOM.

Советы по использованию

  • Для модальных окон стоит всегда включать escapeKey и outsidePress для соответствия стандартам доступности.
  • Если всплывающий элемент содержит интерактивные компоненты (формы, кнопки), необходимо убедиться, что дочерние клики не вызывают преждевременного закрытия.
  • В больших приложениях рекомендуется использовать onDismiss для централизованного управления состоянием, а не напрямую внутри компонента.

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