useInteractions композиция

useInteractions в Floating UI — это мощный хук, предназначенный для объединения нескольких взаимодействий с плавающими элементами (popover, tooltip, dropdown) в единый объект, управляемый через API библиотеки. Его основная задача — обеспечить консистентное управление событиями мыши, клавиатуры и фокуса без необходимости вручную синхронизировать их между разными хуками.


Импорт и базовая структура

import { useInteractions, useClick, useHover, useFocus, useRole } from '@floating-ui/react';

Хук принимает массив других взаимодействий и возвращает объект с методами и пропсами, которые нужно применять к reference и floating элементам:

const { getReferenceProps, getFloatingProps } = useInteractions([
  useClick(context),
  useHover(context),
  useFocus(context),
  useRole(context, { role: 'tooltip' })
]);
  • getReferenceProps — для элемента, который инициирует открытие floating элемента.
  • getFloatingProps — для самого floating элемента.
  • context — объект, создаваемый через useFloating, содержащий состояние и методы управления положением и видимостью.

Комбинирование взаимодействий

useInteractions позволяет комбинировать:

  1. useClick — управление открытием и закрытием по клику.

    const click = useClick(context);

    Позволяет автоматически переключать состояние видимости при кликах на reference и вне него.

  2. useHover — обработка hover-событий.

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

    Поддерживает задержку появления и исчезновения floating элемента, предотвращая резкие всплытия при быстром наведении.

  3. useFocus — управление фокусом для доступности.

    const focus = useFocus(context);

    Обеспечивает открытие при фокусе и закрытие при потере фокуса, что критично для keyboard navigation.

  4. useRole — добавление ARIA-ролей для улучшения доступности.

    const role = useRole(context, { role: 'menu' });

    Автоматически назначает роли, aria-expanded и aria-haspopup.


Пример интеграции всех взаимодействий

const context = useFloating({
  placement: 'bottom',
  middleware: [offset(8), flip(), shift({ padding: 5 })],
});

const interactions = useInteractions([
  useClick(context),
  useHover(context),
  useFocus(context),
  useRole(context, { role: 'tooltip' }),
]);

return (
  <>
    <button {...interactions.getReferenceProps()}>
      Наведи или кликни
    </button>
    {context.isOpen && (
      <div {...interactions.getFloatingProps()}>
        Содержимое всплывающего элемента
      </div>
    )}
  </>
);
  • В этом примере один useInteractions объединяет все ключевые взаимодействия.
  • Не нужно вручную отслеживать состояния hover, focus и click одновременно.
  • Floating элемент автоматически получает правильные props для ARIA и управления событиями.

Опции и тонкая настройка

Каждое взаимодействие принимает свои настройки:

  • useClick:

    • enabled — включить или выключить обработку кликов.
    • toggle — переключение состояния при повторном клике.
  • useHover:

    • enabled — включение/выключение hover.
    • delay — задержка появления и исчезновения, можно задать { open: 200, close: 100 }.
    • restMs — минимальное время до повторного открытия после закрытия.
  • useFocus:

    • enabled — управление только при необходимости.
  • useRole:

    • roletooltip, menu, dialog, listbox и другие.
    • Автоматически управляет атрибутами aria-expanded и aria-controls.

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


Обработка событий в getReferenceProps и getFloatingProps

getReferenceProps и getFloatingProps не только добавляют слушатели событий, но и корректно объединяют их с уже существующими обработчиками:

const buttonProps = interactions.getReferenceProps({
  onClick: () => console.log('Reference clicked'),
});
  • Событие onClick будет выполнено после внутренних обработчиков useClick.
  • Это предотвращает конфликты между библиотечными и пользовательскими обработчиками.

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

  • Всегда использовать единый context через useFloating для всех взаимодействий.
  • useInteractions лучше подключать один раз и распределять пропсы на reference и floating элементы.
  • Настраивать задержки hover и focus для предотвращения “дрожащих” всплывающих элементов.
  • Использовать useRole для соблюдения стандартов доступности и SEO.

Особенности производительности

  • useInteractions минимизирует количество подписок на события, так как объединяет их в один обработчик.
  • Floating UI автоматически оптимизирует ререндеры при изменении видимости и позиции, если все взаимодействия подключены через useInteractions.
  • Можно selectively включать или отключать отдельные взаимодействия для тяжелых страниц, чтобы снизить нагрузку.

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