useContextMenu
Hooks that manage context menu state, right-click positioning, keyboard navigation, and submenu coordination.
Usage#
import { useContextMenu } from '@primereact/headless/contextmenu';
import { useContextMenuSubmenu } from '@primereact/headless/contextmenu/submenu';const contextmenu = useContextMenu();
const sub = useContextMenuSubmenu();
const subTriggerProps = contextmenu.getSubTriggerProps({ value: 'view', sub: sub.menusub });useContextMenu wraps useMenu with right-click activation and cursor-based positioning. See Primitive for a component-based API.
Features#
- Right-click activation —
triggerPropsinterceptscontextmenuevents and anchors the popup at the cursor - Global mode — attach the listener to the whole document so right-clicking anywhere opens the menu
- Two-hook architecture —
useContextMenufor root state,useContextMenuSubmenufor per-submenu behavior - Typed items —
getItemProps({ type })produces menuitem, checkbox, or radio behavior with matching ARIA - Popover integration —
appendTo,baseZIndex, andautoZIndexforward to the internalusePopoverfor portal/stacking control - Type-ahead search — typing characters moves focus to the matching item label
Working with callbacks#
Controlled visibility#
Use open and onOpenChange to drive the popup state externally — useful for showing the menu from a keyboard shortcut or synchronizing with other overlays.
const [open, setOpen] = React.useState(false);
const contextmenu = useContextMenu({
open,
onOpenChange: (e) => setOpen(e.value)
});
<div {...contextmenu.rootProps}>
<div {...contextmenu.triggerProps}></div>
{contextmenu.state.open && (
<div {...contextmenu.positionerProps}>
<div {...contextmenu.popupProps}>
<div {...contextmenu.arrowProps} />
<ul {...contextmenu.getListProps()}>
<li {...contextmenu.getItemProps({ value: 'item1' })}></li>
<li {...sub.subProps}>
<div {...subTriggerProps}></div>
<ul {...contextmenu.getListProps({ value: 'view', sub: sub.menusub })}></ul>
</li>
</ul>
</div>
</div>Document-wide activation#
Set global so any right-click on the page (outside of other context-menu triggers) opens the menu at the cursor.
const contextmenu = useContextMenu({ global: true });Submenus with useContextMenuSubmenu#
Instantiate a useContextMenuSubmenu per submenu and pass its menusub to the root getters to wire hover-to-open and keyboard handoff.
const sub = useContextMenuSubmenu();
const subTriggerProps = contextmenu.getSubTriggerProps({ value: 'files', sub: sub.menusub });
const subListProps = contextmenu.getListProps({ value: 'files', sub: sub.menusub });Checkbox and radio items#
Pass type and checked to getItemProps, and use getIndicatorProps with match to render the check/dot conditionally.
contextmenu.getItemProps({ value: 'notifications', type: 'checkbox', checked: notificationsOn });
contextmenu.getItemProps({ value: 'light', type: 'radio', checked: theme === 'light' });
const indicatorProps = contextmenu.getIndicatorProps({ type: 'checkbox', checked: true, match: 'checked' });Portal and stacking control#
Forward popover configuration through appendTo, baseZIndex, and autoZIndex when embedding inside modals or tight scroll containers.
const contextmenu = useContextMenu({
appendTo: 'body',
baseZIndex: 0,
autoZIndex: true
});Styling with data attributes#
All prop getters attach data-scope="contextmenu" and a data-part attribute for CSS targeting. Additional data attributes reflect runtime state:
triggerProps—data-part="trigger"getItemProps—data-part="item", plusdata-value,data-focused,data-disabled,data-checkedgetSubTriggerProps—data-part="subtrigger", plusdata-value,data-focused,data-disabled,data-opengetIndicatorProps—data-part="indicator", plusdata-open/data-closedordata-checked/data-unchecked
[data-scope='contextmenu'][data-part='item'][data-focused] {
background-color: var(--surface-hover);
}
[data-scope='contextmenu'][data-part='subtrigger'][data-open] {
background-color: var(--surface-hover);
}
[data-scope='contextmenu'][data-part='item'][data-disabled] {
opacity: 0.6;
pointer-events: none;
}API#
useContextMenu#
| Name | Type | Default |
|---|---|---|
global | boolean | false |
| Attaches the menu to document instead of a particular element. | ||
open | boolean | — |
| Controlled open state of the menu. | ||
defaultOpen | boolean | false |
| Default open state for uncontrolled mode. | ||
appendTo | "body" | HTMLElement | "self" | 'body' |
| The element to which the overlay is appended. | ||
baseZIndex | number | 0 |
| Base zIndex value to use in layering. | ||
autoZIndex | boolean | true |
| Whether to automatically manage layering. | ||
tabIndex | number | 0 |
| Index of the element in tabbing order. | ||
openDelay | number | 100 |
| The delay in milliseconds before opening the menu when hovering the trigger. Only applies when `openOnHover` is true. | ||
closeDelay | number | 0 |
| The delay in milliseconds before closing the menu when the pointer leaves the trigger. Only applies when `openOnHover` is true. | ||
openOnHover | boolean | false |
| When true, the menu opens on pointer hover over the trigger (in addition to click). | ||
onOpenChange | (event: useMenuOpenChangeEvent) => void | — |
| Callback to invoke when the open state changes. | ||
context | useMenuSubmenuExposes | — |
| Optional parent submenu context whose popover state should drive this menu. When provided, useMenu reuses the parent submenu's popover (anchor, open state, positioner) instead of creating its own. Forwarded by Menu.Root automatically when nested inside a Menu.Submenu. | ||
navigationmenu | useNavigationMenuExposes | — |
| Optional parent NavigationMenu context. When provided, ArrowRight / ArrowLeft pressed on a list item that is not a submenu trigger will move focus to the next / previous sibling navigationmenu trigger (WAI-ARIA NavigationMenu pattern). Forwarded by Menu.Root when nested inside a `NavigationMenu` . | ||
navigationmenuMenuId | string | — |
| The id this menu is registered under in the parent NavigationMenu's trigger registry. Required for `navigationmenu` sibling navigation to know which trigger is "current". | ||
useContextMenuSubmenu#
| Name | Type | Default |
|---|---|---|
open | boolean | — |
| Controlled open state of the submenu. | ||
defaultOpen | boolean | false |
| Default open state for uncontrolled mode. | ||
disabled | boolean | false |
| Whether the submenu is disabled. | ||
openDelay | number | 100 |
| The delay in milliseconds before opening the submenu when hovering the subtrigger. Only applies when `openOnHover` is true. | ||
closeDelay | number | 0 |
| The delay in milliseconds before closing the submenu when the pointer leaves the subtrigger. Only applies when `openOnHover` is true. | ||
openOnHover | boolean | true |
| When true, the submenu opens on pointer hover over the subtrigger. | ||
onOpenChange | (event: useMenuSubmenuOpenChangeEvent) => void | — |
| Callback to invoke when the open state changes. | ||
Accessibility#
Right-click or long-press opens the menu, Arrow keys navigate, Enter activates, and Escape dismisses. See Primitive for full WAI-ARIA compliance details.