Подменю и вложенность

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

Структура вложенного меню

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

  1. Menu – контейнер для списка опций.
  2. MenuItem – отдельная опция меню.
  3. MenuTrigger – элемент, который управляет открытием подменю.
  4. MenuSection – опционально, для группировки элементов меню.

Для вложенного меню ключевым моментом является использование MenuTrigger внутри MenuItem, что позволяет создавать иерархию.

import { useMenu, useMenuItem, useMenuTrigger, MenuTrigger } from '@react-aria/menu';
import { useButton } from '@react-aria/button';
import { useOverlayTriggerState } from '@react-stately/overlays';

function NestedMenu() {
  let state = useOverlayTriggerState({});
  
  let triggerRef = React.useRef();
  let { menuTriggerProps, menuProps } = useMenuTrigger({}, state, triggerRef);
  let { buttonProps } = useButton(menuTriggerProps, triggerRef);
  
  return (
    <>
      <button {...buttonProps} ref={triggerRef}>
        Основное меню
      </button>
      {state.isOpen && (
        <Menu {...menuProps}>
          <MenuItem key="1">Элемент 1</MenuItem>
          <MenuItem key="2">
            <MenuTrigger>
              Подменю
              <NestedSubMenu />
            </MenuTrigger>
          </MenuItem>
          <MenuItem key="3">Элемент 3</MenuItem>
        </Menu>
      )}
    </>
  );
}

Управление состоянием подменю

Для корректного открытия и закрытия вложенных меню используется useOverlayTriggerState из React Stately. Этот хук обеспечивает контроль над видимостью меню, синхронизацию фокуса и возможность закрытия подменю при клике вне него или при навигации клавиатурой.

import { useOverlayTriggerState } from '@react-stately/overlays';

let subMenuState = useOverlayTriggerState({});

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

Атрибуты доступности (ARIA)

Подменю требуют правильного указания атрибутов ARIA:

  • aria-haspopup=“menu” – указывает, что элемент открывает подменю.
  • aria-expanded – отражает текущее состояние открытости подменю.
  • role=“menu” и role=“menuitem” – обозначают контейнер меню и отдельные пункты.
  • aria-controls – связывает триггер с конкретным подменю.

React Aria автоматически назначает эти атрибуты через хуки useMenu, useMenuItem и useMenuTrigger, но при кастомной разметке важно проверять их присутствие.

Навигация с клавиатуры

Вложенные меню должны поддерживать клавиатурную навигацию:

  • Стрелки вверх/вниз – переход между элементами текущего меню.
  • Стрелка вправо – открытие подменю.
  • Стрелка влево – закрытие подменю и возврат к родительскому меню.
  • Escape – закрытие текущего подменю и возврат фокуса к триггеру.
  • Enter / Space – активация элемента меню.

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

Работа с динамическими данными

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

<Menu {...menuProps}>
  {items.map(item => (
    <MenuItem key={item.id}>{item.name}</MenuItem>
  ))}
</Menu>

Комбинация с другими компонентами интерфейса

Вложенные меню в React Aria легко интегрируются с:

  • Toolbar – для создания сложных панелей инструментов.
  • ContextMenu – вызов подменю по правому клику.
  • Dropdown – как часть выпадающих списков с несколькими уровнями.

Для всех случаев сохраняется единая логика управления состоянием и доступности, что позволяет строить сложные интерфейсы без нарушения стандартов ARIA.

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

  • Минимизировать количество одновременно открытых подменю.
  • Использовать ленивую загрузку подменю через условный рендеринг.
  • Избегать глубоких вложенностей без необходимости, чтобы уменьшить сложность управления фокусом и событий.

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