Radix UI предоставляет мощный набор компонентов для создания
контекстных меню в React-приложениях, которые полностью
управляются состоянием и доступны для пользователей с различными
потребностями (accessibility-first). Основной модуль для работы с
контекстными меню — это @radix-ui/react-context-menu.
Контекстное меню состоит из нескольких ключевых элементов: корневого контейнера, триггера, контента и пунктов меню.
import * as ContextMenu from '@radix-ui/react-context-menu';
ContextMenu.Root — корневой компонент, который
оборачивает все элементы контекстного меню. Он управляет состоянием
открытия/закрытия и обеспечивает корректное взаимодействие с
пользователем.ContextMenu.Trigger — элемент, с которого вызывается
меню, обычно это правый клик или определённое действие.ContextMenu.Content — визуальный контейнер для пунктов
меню. Поддерживает стилизацию и позиционирование с помощью CSS или
Tailwind.ContextMenu.Item — отдельный пункт меню. Поддерживает
события onSelect, управление фокусом и состояния
disabled и highlighted.ContextMenu.Separator — визуальный разделитель между
группами пунктов.ContextMenu.Sub и ContextMenu.SubContent —
для вложенных подменю.Простейшая структура меню выглядит следующим образом:
<ContextMenu.Root>
<ContextMenu.Trigger>
<div className="box">Клик правой кнопкой</div>
</ContextMenu.Trigger>
<ContextMenu.Content className="menu">
<ContextMenu.Item onSel ect={() => console.log('Скопировано')}>Копировать</ContextMenu.Item>
<ContextMenu.Item onSel ect={() => console.log('Вставлено')}>Вставить</ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item disabled>Удалить</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
Особенности реализации:
ContextMenu.Trigger может быть любым React-элементом.
Меню будет отображаться при взаимодействии с этим элементом.ContextMenu.Content поддерживает
позиционирование через props side
(top, right, bottom,
left) и align (start,
center, end).ContextMenu.Item может быть интерактивным или
неактивным (disabled). При использовании
onSelect можно привязать любую функцию.Radix UI использует внутреннее управление состоянием, что упрощает
работу с фокусом и доступностью. Дополнительно можно контролировать
состояние через prop open:
const [open, setOpen] = React.useState(false);
<ContextMenu.Root open={open} onOpenCha nge={setOpen}>
<ContextMenu.Trigger>Меню</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item onSel ect={() => setOpen(false)}>Закрыть</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
Такой подход позволяет синхронизировать меню с внешним состоянием, что удобно при сложных интерфейсах, где несколько компонентов могут открывать одно и то же меню.
Radix UI поддерживает создание многоуровневых контекстных меню с
помощью ContextMenu.Sub и
ContextMenu.SubContent.
<ContextMenu.Item>
Дополнительно
<ContextMenu.Sub>
<ContextMenu.SubTrigger>Открыть подменю</ContextMenu.SubTrigger>
<ContextMenu.SubContent>
<ContextMenu.Item onSel ect={() => console.log('Подпункт 1')}>Подпункт 1</ContextMenu.Item>
<ContextMenu.Item onSel ect={() => console.log('Подпункт 2')}>Подпункт 2</ContextMenu.Item>
</ContextMenu.SubContent>
</ContextMenu.Sub>
</ContextMenu.Item>
Особенности вложенных меню:
SubTrigger — пункт, при наведении или клике на который
открывается подменю.SubContent — контейнер для подменю с возможностью
полного контроля позиционирования.Radix UI не накладывает стили по умолчанию, предоставляя полную свободу кастомизации:
.menu {
background-color: white;
border: 1px solid #ccc;
border-radius: 6px;
padding: 5px;
min-width: 180px;
}
.menu-item {
padding: 5px 10px;
cursor: pointer;
}
.menu-item:hover {
background-color: #f0f0f0;
}
Для анимации открытия можно использовать CSS-переходы:
.menu[data-state='open'] {
animation: fadeIn 150ms ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-5px); }
to { opacity: 1; transform: translateY(0); }
}
Radix UI автоматически обрабатывает:
Escape.aria-disabled и
aria-haspopup для подменю.Это позволяет создавать контекстные меню, соответствующие WCAG без дополнительной реализации логики взаимодействия с клавиатурой.
ContextMenu.Item, включая компоненты с иконками, чекбоксы
или переключатели.ContextMenu.Content можно
рендерить через портал для управления z-index и расположением вне
основного DOM.ref и методы focus().onOpenChange,
onSelect, onEscapeKeyDown позволяют
интегрировать меню с другими компонентами приложения.Эта структура позволяет создавать гибкие, доступные и полностью настраиваемые контекстные меню, которые легко интегрируются в современные React-приложения и поддерживают любые UI-требования.