Radix UI предоставляет гибкую архитектуру для создания интерфейсных компонентов, в том числе меню. Множественные меню позволяют объединять несколько уровней вложенности или несколько связанных контекстных меню, сохраняя согласованное управление состоянием и взаимодействиями пользователя.
Основной строительный блок меню в Radix UI — это Menu,
который состоит из следующих элементов:
Menu.Root — корневой контейнер меню,
управляющий состоянием открытия и закрытия.Menu.Trigger — элемент, который
инициирует открытие меню (например, кнопка).Menu.Content — контейнер для элементов
меню.Menu.Item — отдельный элемент
меню.Menu.Sub / Menu.SubTrigger /
Menu.SubContent — элементы для вложенных
подменю.Menu.Separator — визуальный
разделитель элементов меню.Menu.Label — заголовок или подпись для
группы элементов меню.Для множественных меню особенно важны Menu.Sub и
Menu.SubTrigger, так как они позволяют строить древовидную
структуру.
import * as Menu from '@radix-ui/react-menu';
function MultiLevelMenu() {
return (
<Menu.Root>
<Menu.Trigger>Открыть меню</Menu.Trigger>
<Menu.Content>
<Menu.Item>Пункт 1</Menu.Item>
<Menu.Sub>
<Menu.SubTrigger>Пункт 2 (с подменю)</Menu.SubTrigger>
<Menu.SubContent>
<Menu.Item>Подпункт 2.1</Menu.Item>
<Menu.Item>Подпункт 2.2</Menu.Item>
<Menu.Sub>
<Menu.SubTrigger>Подменю 2.3</Menu.SubTrigger>
<Menu.SubContent>
<Menu.Item>Подпункт 2.3.1</Menu.Item>
</Menu.SubContent>
</Menu.Sub>
</Menu.SubContent>
</Menu.Sub>
<Menu.Item>Пункт 3</Menu.Item>
</Menu.Content>
</Menu.Root>
);
}
В этом примере реализовано три уровня меню: основной, вложенный и
дополнительное подменю внутри вложенного. Menu.Sub
автоматически управляет позиционированием и открытием вложенного меню
при наведении или фокусе.
Radix UI использует контролируемый и неконтролируемый подход к состоянию компонентов:
Menu.Root сам
управляет открытием и закрытием, на основе взаимодействия с
Menu.Trigger.open и обработчика onOpenChange можно
синхронизировать состояние меню с внешним состоянием приложения.<Menu.Root open={isOpen} onOpenCha nge={setIsOpen}>
<Menu.Trigger>Меню</Menu.Trigger>
<Menu.Content>
<Menu.Item onSel ect={() => console.log("Выбрано")}>Пункт</Menu.Item>
</Menu.Content>
</Menu.Root>
Контролируемый режим особенно полезен, когда несколько меню должны взаимодействовать друг с другом: например, закрывать все подменю при закрытии основного меню.
align и
side — позволяют задать расположение
подменю относительно триггера (start, center,
end для выравнивания и top,
bottom, left, right для
стороны).sideOffset — отступ подменю от
триггера.data-state="open" и data-state="closed", для
управления анимациями через @keyframes или transition.[data-state="open"] {
animation: fadeIn 200ms ease-out;
}
[data-state="closed"] {
animation: fadeOut 150ms ease-in;
}
Radix UI автоматически обеспечивает:
Escape.Для множественных меню важно следить за корректной фокусной цепочкой, чтобы пользователь мог переходить между уровнями меню без потери контекста.
Меню может строиться на основе данных:
const menuItems = [
{ label: "Файл" },
{
label: "Правка",
subItems: [
{ label: "Копировать" },
{ label: "Вставить" },
]
},
{ label: "Вид" }
];
function DynamicMenu() {
return (
<Menu.Root>
<Menu.Trigger>Меню</Menu.Trigger>
<Menu.Content>
{menuItems.map((item, idx) => item.subItems ? (
<Menu.Sub key={idx}>
<Menu.SubTrigger>{item.label}</Menu.SubTrigger>
<Menu.SubContent>
{item.subItems.map((sub, subIdx) => (
<Menu.Item key={subIdx}>{sub.label}</Menu.Item>
))}
</Menu.SubContent>
</Menu.Sub>
) : (
<Menu.Item key={idx}>{item.label}</Menu.Item>
))}
</Menu.Content>
</Menu.Root>
);
}
Данный подход позволяет создавать масштабируемые иерархические меню, которые могут меняться на основе состояния приложения или данных с сервера.
onOpenChange.sideOffset и align можно управлять положением
подменю, чтобы они не выходили за пределы окна.Popover или
Dialog, если нужно более сложное поведение.Множественные меню в Radix UI обеспечивают гибкость, масштабируемость и высокую доступность интерфейсов, сохраняя простоту управления состоянием и поведением. Их архитектура позволяет строить глубоко вложенные структуры с контролируемой логикой и адаптивным позиционированием.