useMenuTriggerState для меню

useMenuTriggerState — это хук из библиотеки React Aria, предназначенный для управления состоянием триггеров меню. Он обеспечивает корректную работу меню в сочетании с aria-атрибутами, гарантируя доступность и предсказуемое поведение компонентов интерфейса. Основная задача хука — контролировать открытие и закрытие меню, отслеживать выбранный элемент и взаимодействие с пользователем.


Импорт и базовое использование

Для начала хук подключается следующим образом:

import { useMenuTriggerState } from "@react-stately/menu";

useMenuTriggerState возвращает объект состояния с ключевыми свойствами и методами:

  • isOpen — булево значение, указывающее, открыто ли меню.
  • toggle — функция переключения состояния меню (открыть/закрыть).
  • open — функция принудительного открытия меню.
  • close — функция принудительного закрытия меню.
  • selectedKey — ключ выбранного элемента меню.
  • setSelectedKey — функция для изменения выбранного элемента.

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

import { useMenuTriggerState } from "@react-stately/menu";

function MyMenu() {
  const state = useMenuTriggerState({});

  return (
    <>
      <button onCl ick={state.toggle}>
        Открыть меню
      </button>
      {state.isOpen && (
        <ul>
          <li onCl ick={() => state.setSelectedKey('item1')}>Пункт 1</li>
          <li onCl ick={() => state.setSelectedKey('item2')}>Пункт 2</li>
        </ul>
      )}
    </>
  );
}

Здесь state.toggle автоматически меняет isOpen, а setSelectedKey фиксирует выбранный элемент.


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

useMenuTriggerState принимает объект с опциями:

  • defaultOpen — начальное состояние меню (true/false).
  • onOpenChange — коллбек, вызываемый при изменении состояния открытия.
  • selectionMode — режим выбора, принимает 'single' или 'none'. Если 'single', выбирается один элемент меню.
  • disallowEmptySelection — булево значение, запрещающее снятие выделения (актуально при selectionMode: 'single').

Пример с настройкой:

const state = useMenuTriggerState({
  defaultOpen: false,
  selectionMode: 'single',
  onOpenChange: (isOpen) => console.log('Меню открыто:', isOpen)
});

Интеграция с компонентами меню

Хук лучше всего использовать вместе с MenuTrigger и Menu из React Aria для полноценной доступной реализации:

import { Menu, MenuTrigger, Item } from "@react-aria/menu";

function AccessibleMenu() {
  const state = useMenuTriggerState({ selectionMode: 'single' });

  return (
    <MenuTrigger>
      <button {...state.toggle}>Меню</button>
      {state.isOpen && (
        <Menu>
          <Item key="1" onPr ess={() => state.setSelectedKey('1')}>Пункт 1</Item>
          <Item key="2" onPr ess={() => state.setSelectedKey('2')}>Пункт 2</Item>
        </Menu>
      )}
    </MenuTrigger>
  );
}

Использование Item гарантирует корректную работу с клавиатурной навигацией и aria-атрибутами, а состояние управляется через useMenuTriggerState.


Управление открытием и закрытием

Методы open, close и toggle позволяют реализовать:

  • Автоматическое закрытие при выборе элемента
  • Открытие меню при фокусе или наведении
  • Управление состоянием из внешнего компонента

Пример закрытия меню после выбора элемента:

<Item key="1" onPr ess={() => state.close()}>Пункт 1</Item>

Выбор элемента и контроль состояния

selectedKey и setSelectedKey обеспечивают точное управление выбранным пунктом:

console.log('Выбранный элемент:', state.selectedKey);
state.setSelectedKey('2');

С использованием selectionMode: 'single' гарантируется, что в любой момент будет выделен ровно один пункт, если не активирована опция disallowEmptySelection: false.


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

  • Для доступности всегда использовать комбинацию MenuTrigger + Menu + Item с useMenuTriggerState.
  • Если требуется меню с множественным выбором, лучше использовать selectionMode: 'multiple' в сочетании с другими состояниями React Aria.
  • Для сложных меню с динамическим содержимым состояние можно синхронизировать с внешними данными через selectedKey и onOpenChange.
  • Не использовать useState напрямую для управления открытием, чтобы не потерять совместимость с aria-атрибутами и клавиатурной навигацией.

Интеграция с клавиатурой и доступностью

React Aria автоматически добавляет необходимые атрибуты для поддержки экранных читалок:

  • aria-haspopup и aria-expanded для кнопки-триггера
  • aria-selected для элементов меню
  • Поддержка навигации стрелками, Enter и Escape

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


useMenuTriggerState превращает меню в полностью управляемый и доступный компонент, упрощая разработку интерактивных интерфейсов с соблюдением стандартов доступности и корректной работы с клавиатурой.