useRole хук

useRole — это специализированный хук библиотеки Floating UI, который управляет поведением элементов интерфейса с точки зрения их семантической роли и взаимодействия с пользователем. Основная задача хука — упрощение работы с интерактивными компонентами, такими как всплывающие подсказки (tooltips), контекстные меню, диалоги и меню выбора, обеспечивая корректное управление атрибутами ARIA, позиционированием и событиями.


Основные принципы работы

Хук useRole строится вокруг триады: элемент-роль-позиция:

  1. Элемент — DOM-узел, которому назначается интерактивная роль.
  2. Роль — ARIA-атрибут, определяющий тип компонента (menu, tooltip, dialog, listbox и другие).
  3. Позиция — координаты, вычисляемые через Floating UI, определяющие положение всплывающего элемента относительно триггера.

Хук возвращает объект с ключевыми свойствами:

  • reference — реф для триггер-элемента.
  • floating — реф для всплывающего окна.
  • roleProps — набор атрибутов и обработчиков событий, обеспечивающих корректную работу роли.
  • context — объект, позволяющий синхронизировать поведение между триггером и всплывающим элементом.

Инициализация useRole

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

import { useRole } from '@floating-ui/react';

const { reference, floating, roleProps } = useRole({
  role: 'tooltip',
  open: true
});

Пояснения:

  • role: 'tooltip' — назначение роли ARIA.
  • open: true — контролируемое состояние видимости компонента.
  • reference и floating используются для привязки DOM-узлов.
  • roleProps автоматически добавляет необходимые атрибуты, например aria-hidden, aria-labelledby, aria-expanded, а также обработчики событий для открытия/закрытия.

Роли и их особенности

useRole поддерживает большинство стандартных ARIA-ролей для интерактивных элементов:

Роль Описание Особенности работы с useRole
tooltip Всплывающая подсказка, связанная с элементом. Автоматически управляет aria-describedby.
menu Контекстное меню или раскрывающийся список. Поддержка клавиатурной навигации (ArrowUp/ArrowDown).
dialog Модальное окно. Управляет фокусом и видимостью через aria-modal.
listbox Список выбора. Интеграция с клавиатурными событиями для перемещения между опциями.

Каждая роль в useRole накладывает определенные ARIA-атрибуты и поведение, позволяя не дублировать обработчики вручную.


Свойства roleProps

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

<div ref={floating} {...roleProps}>
  Tooltip content
</div>

Ключевые свойства, входящие в roleProps:

  • role — назначенная ARIA-роль.
  • aria-hidden — скрывает элемент от скринридеров, если он закрыт.
  • id и aria-labelledby / aria-describedby — связывают триггер и всплывающее окно.
  • События мыши и клавиатуры — автоматически обработка focus, blur, mouseenter, mouseleave, keydown.

Синхронизация открытого состояния

useRole поддерживает как контролируемый, так и неконтролируемый режим управления видимостью:

const [open, setOpen] = useState(false);

const { reference, floating, roleProps } = useRole({
  role: 'menu',
  open,
  onOpenChange: setOpen
});
  • open — текущее состояние видимости.
  • onOpenChange — коллбек для обработки изменений состояния.
  • Это позволяет интегрировать хук в сложные компоненты с внешним управлением состояния.

Интеграция с Floating UI позиционированием

useRole тесно работает с хук-цепочкой useFloating:

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

const floatingData = useFloating({
  placement: 'bottom-start',
  middleware: [offset(8), flip()]
});

const { reference, floating, roleProps } = useRole({
  role: 'tooltip',
  open: true
});

// Связываем DOM-узлы с useFloating
return (
  <>
    <button ref={reference}>Hover me</button>
    <div ref={floating} style={floatingData.floatingStyles} {...roleProps}>
      Tooltip content
    </div>
  </>
);

Пояснения:

  • useFloating вычисляет позицию всплывающего элемента.
  • roleProps гарантирует корректное поведение ARIA и обработку событий.
  • Совместное использование обеспечивает доступность и точное позиционирование без дополнительных оберток.

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

useRole автоматически добавляет обработку:

  • Arrow keys — перемещение между элементами (для меню, listbox).
  • Escape — закрытие всплывающих элементов.
  • Enter / Space — активация опций.
  • Focus management — автоматическая установка фокуса на первый элемент при открытии диалога или меню.

Настройка пользовательских событий

В useRole можно переопределить обработчики через roleProps:

<div
  ref={floating}
  {...roleProps}
  onMouseEn ter={(e) => {
    roleProps.onMouseEnter(e); // сохраняем стандартное поведение
    console.log('Tooltip hovered');
  }}
>
  Tooltip content
</div>

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


Поддержка нескольких ролей и вложенных элементов

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

const { reference, floating: menuFloating, roleProps: menuProps } = useRole({ role: 'menu', open: openMenu });
const { floating: tooltipFloating, roleProps: tooltipProps } = useRole({ role: 'tooltip', open: openTooltip });
  • В этом случае каждый элемент получает собственные атрибуты и обработчики.
  • Состояния open синхронизируются отдельно, что обеспечивает модульность.

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