ContextMenu
A right-click context menu that appears at the cursor position. Use to provide contextual actions for specific elements or regions without cluttering the UI with visible buttons.
Installation
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0
Requires React 19+, base CSS and a Theme provider. See Setup.
Context Menu
A right-click context menu that appears at the cursor position. Use to provide contextual actions for specific elements or regions without cluttering the UI with visible buttons.
| Prop | Type | Default | Description |
|---|---|---|---|
| children * | ReactNode | The trigger area: right-click on this content to open the menu. | |
| items * | ContextMenuOption[] | Array of menu entries. Each entry is one of: an action item {label, onClick?, icon?, isDisabled?, variant?, items?} (nested items open a flyout in popover presentation and drill into a new view in bottom-sheet presentation; variant "destructive" renders it in the error color), a divider {type: "divider"}, or a section {type: "section", title?, items: [...action items]}. | |
| menuContent | ReactNode | Custom JSX menu content for compound mode. Use instead of items for dynamic or stateful menus. | |
| menuWidth | number | string | '160px' | Custom menu width. |
| size | 'sm' | 'md' | 'lg' | 'md' | Size of menu items: controls padding density. |
| label | string | 'Context menu' | Accessible name for the menu surface, announced when it opens. |
| onOpenChange | (isOpen: boolean) => void | Callback fired when the menu opens or closes. | |
| presentation | 'popover' | 'bottom-sheet' | 'adaptive' | 'popover' | Presentation policy. popover opens at the pointer position, bottom-sheet always uses an action sheet, and adaptive uses the BottomSheet at 768px and below when the primary pointer is coarse. |
| isDisabled | boolean | false | When true, right-click shows the native browser context menu instead. |
| triggerXstyle | StyleXStyles | StyleXStyles[] | Styles applied to the trigger wrapper. Accepts stylex.create() values, not inline style objects. | |
| triggerAs | 'div' | 'span' | 'div' | The element the trigger wrapper renders as. 'div' is a block; 'span' an inline wrapper, so a reference inside prose can own a context menu without breaking the text flow. |
Usage guidance
- Keep menu items concise and action-oriented; users expect quick access to contextual actions.
- Use sections and dividers to group related actions when the menu has many items.
- Use
presentation="adaptive"when right-click should remain cursor-positioned on desktop while long-press opens a reachable BottomSheet on compact touch devices. - Ensure all context menu actions are also accessible via other UI elements for keyboard-only users.
- Keep a visible MoreMenu or equivalent trigger for important mobile actions; long-press must not be the only route.
- Avoid: Use a ContextMenu as the only way to access important actions; not all users know to right-click.
- Avoid: Place more than 10–12 items in a single menu without grouping them into sections.
Theming API
{
"targets": [
{
"className": "astryx-context-menu"
}
],
"vars": [
{
"name": "--_dropdown-menu-radius",
"description": "Border radius of the menu popup",
"default": "var(--radius-container)",
"private": true
},
{
"name": "--_dropdown-menu-padding",
"description": "Inner padding of the menu popup",
"default": "var(--spacing-1)",
"private": true
}
],
"derived": [
{
"property": "borderRadius",
"vars": [
"--_dropdown-menu-radius"
]
},
{
"property": "padding",
"vars": [
"--_dropdown-menu-padding"
]
}
]
}
ContextMenuItem
Anatomy
- Trigger area: Caller-provided region that accepts right-click, keyboard context-menu, and long-press input.
- Pointer menu surface: Cursor-positioned menu panel used by the pointer presentation.
- Pointer action row: DropdownMenu-owned action, selectable option, or submenu row in the pointer presentation.
- Touch sheet frame: BottomSheet panel, content area, handle, and optional scrim that host touch actions.
- Touch menu surface: ContextMenu-owned content panel rendered inside the touch sheet frame.
- Touch action list: Spacious List that groups data-driven touch actions.
- Touch action row: ListItem button used for a data-driven action or drill-in entry in the touch presentation.
Context Menu Item
Menu item component for compound mode. Re-exported from DropdownMenuItem for discoverability.
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | IconType | Icon to display before the label. | |
| label | ReactNode | Primary label text. | |
| description | ReactNode | Secondary description text displayed below the label. | |
| endContent | ReactNode | Additional content rendered after the label and description. | |
| xstyle | StyleXStyles | StyleX styles for layout customization. |
Examples
- Context Menu Item: Context menu with custom-rendered items using ContextMenuItem for icons and descriptions.
- Context Menu: An adaptive context area that supports long-press on compact touch screens and right-click elsewhere.
- ContextMenu — Basic: An adaptive context area: long-press opens a BottomSheet on compact touch screens, while right-click opens a cursor-positioned menu elsewhere.
- ContextMenu — Bottom Sheet: A ContextMenu using the explicit BottomSheet presentation. Long-press the target on touch devices or right-click it with a pointer. Keep a visible menu trigger for important mobile actions.
- ContextMenuItem — Basic: Context menu items with labels and secondary descriptions. Use ContextMenuItem to render custom menu entries with consistent styling.
Complete example dependencies
Some examples import optional icons. The per-example install command in the examples list identifies exactly what that example needs. For all examples on this page:
npm install @heroicons/react@2.2.0