useHover хук

useHover — это хук, предоставляемый библиотекой Floating UI, который упрощает управление состоянием всплывающих элементов при наведении курсора. Он тесно интегрируется с остальными хуками Floating UI, такими как useFloating, и позволяет реализовать интерактивные подсказки, всплывающие меню, тултипы и прочие элементы интерфейса, которые реагируют на наведение мыши.

Хук возвращает объект с набором свойств и функций, которые позволяют контролировать поведение при наведении: активацию, деактивацию, задержки и связывание с целевым элементом.


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

const hover = useHover(context, options);
  • context — объект, возвращаемый из useFloating. Он содержит состояние и методы позиционирования для всплывающего элемента.
  • options — объект с дополнительными настройками. Основные ключи:
  1. enabledboolean. Определяет, активен ли хук. Если false, обработчики наведения не будут подключены.
  2. delay — задержка перед открытием и закрытием всплывающего элемента. Может быть числом (миллисекунды) или объектом:
delay: {
  open: 200,   // задержка перед открытием
  close: 150   // задержка перед закрытием
}
  1. handleClose — функция, которая вызывается при закрытии элемента. Полезно для кастомной логики закрытия.
  2. mouseOnlyboolean. Если true, хук будет реагировать только на мышь и игнорировать касания на сенсорных устройствах.

Возвращаемые значения

Хук возвращает объект, содержащий:

  • getReferenceProps — функцию, которая объединяет события и пропсы для целевого элемента (того, на который наводят курсор).
  • getFloatingProps — функцию для всплывающего элемента, которая управляет внутренней логикой открывания/закрывания при наведении.
  • open — состояние открытости всплывающего элемента.
  • setOpen — функция для программного управления открытием и закрытием.

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

import { useFloating, useHover, offset, flip } from '@floating-ui/react';

function Tooltip({ children, content }) {
  const { x, y, reference, floating, strategy, context } = useFloating({
    middleware: [offset(8), flip()],
  });

  const hover = useHover(context, { delay: { open: 100, close: 50 } });

  return (
    <>
      <div ref={reference} {...hover.getReferenceProps()}>
        {children}
      </div>
      {hover.open && (
        <div
          ref={floating}
          style={{ position: strategy, top: y ?? 0, left: x ?? 0 }}
          {...hover.getFloatingProps()}
        >
          {content}
        </div>
      )}
    </>
  );
}

Работа с задержками

delay позволяет настроить плавность появления и скрытия элементов. Можно использовать одинаковую задержку или разные значения для открытия и закрытия:

useHover(context, {
  delay: {
    open: 200,
    close: 100
  }
});

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


Интеграция с другими хуками Floating UI

useHover идеально сочетается с:

  • useClick — для управления открытием по клику. Можно комбинировать поведение, например, открывать по наведению, а оставлять открытым при клике.
  • useDismiss — для закрытия по клику вне элемента или при нажатии клавиши Escape.
  • useRole — для корректного указания ARIA-ролей, например tooltip или menu.

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

const hover = useHover(context, { delay: 150 });
const dismiss = useDismiss(context);
const role = useRole(context, { role: 'tooltip' });

<div ref={reference} {...hover.getReferenceProps()} {...dismiss.getReferenceProps()}>
  Наведи на меня
</div>
<div ref={floating} {...hover.getFloatingProps()} {...dismiss.getFloatingProps()} {...role.getFloatingProps()}>
  Всплывающая подсказка
</div>

Особенности работы на сенсорных устройствах

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

useHover(context, { mouseOnly: true });

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


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

  • Использовать delay для устранения мерцания элементов при быстром перемещении курсора.
  • Комбинировать useHover с useDismiss и useRole для лучшей доступности и управления закрытием.
  • Подключать только к элементам, где наведение имеет смысл, чтобы не перегружать интерфейс лишними обработчиками.
  • Следить за производительностью: слишком большое количество активных hover-обработчиков может замедлять интерфейс на больших страницах.

Итоговое понимание

useHover — это мощный инструмент для управления состоянием всплывающих элементов при наведении курсора. Он полностью контролирует открытие и закрытие через задержки, позволяет интегрироваться с другими хуками Floating UI и обеспечивает корректное поведение на разных устройствах. Его грамотное применение делает интерфейс плавным, интерактивным и удобным для пользователя.