useContextMenu
Hooks that manage context menu state, right-click positioning, keyboard navigation, and submenu coordination.
Usage#
import { useContextMenu } from '@primereact/headless/contextmenu';
import { useContextMenuSub } from '@primereact/headless/contextmenu/sub';
const contextmenu = useContextMenu();
const sub = useContextMenuSub();
const subTriggerProps = contextmenu.getSubTriggerProps({ value: 'view', sub: sub.menusub });
return (
<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>
)}
</div>
);useContextMenu wraps useMenu with right-click activation and cursor-based positioning — see Primitive for a component-based API.
Features#
- Two-hook architecture:
useContextMenufor root state,useContextMenuSubfor per-submenu behavior - Returns spread-ready prop objects:
rootProps,triggerProps,popupProps,positionerProps,arrowProps - Dynamic prop getters:
getItemProps,getSubTriggerProps,getListProps,getIndicatorProps - Right-click activation with automatic cursor-based popup positioning
- Global mode to attach context menu to the entire document
- Checkbox and radio item types via
getItemProps({ type: 'checkbox' | 'radio' }) - Built-in character search to jump to items by typing
Behavior#
Right-Click Trigger#
Spread triggerProps on the target element. Right-clicking fires onContextMenu, which positions a virtual anchor at the cursor and opens the popup.
const contextmenu = useContextMenu();
<div {...contextmenu.triggerProps}>Right-click me</div>;Global Mode#
Set global to attach the context menu listener to the entire document instead of a specific trigger element.
const contextmenu = useContextMenu({ global: true });When global is enabled, right-clicking anywhere on the page (outside other contextmenu triggers) opens the popup at the cursor position.
Controlled Visibility#
Use open and onOpenChange for programmatic control over the popup state.
const [open, setOpen] = React.useState(false);
const contextmenu = useContextMenu({
open,
onOpenChange: (e) => setOpen(e.value)
});Submenus#
Use useContextMenuSub for each submenu. Pass the menusub instance to getSubTriggerProps and getListProps to wire up hover-to-open behavior and keyboard navigation across levels.
const sub = useContextMenuSub();
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 for checkbox or radio behavior. Use getIndicatorProps with match to control indicator visibility.
contextmenu.getItemProps({ value: 'notifications', type: 'checkbox', checked: true });
contextmenu.getItemProps({ value: 'light', type: 'radio', checked: selectedTheme === 'light' });
const indicatorProps = contextmenu.getIndicatorProps({ type: 'checkbox', checked: true, match: 'checked' });Popup Positioning#
The hook uses usePopover internally. The popup is positioned relative to a virtual anchor placed at the cursor coordinates. Use appendTo, baseZIndex, and autoZIndex to control portal insertion and stacking.
const contextmenu = useContextMenu({ appendTo: 'body', baseZIndex: 0, autoZIndex: true });Custom 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", plus data-value, data-focused, data-disabled, and data-checked (for checkbox/radio items).
getSubTriggerProps — data-part="subtrigger", plus data-value, data-focused, data-disabled, and data-open (when its submenu is expanded).
getIndicatorProps — data-part="indicator", plus data-open/data-closed or data-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. | ||
onOpenChange | (event: useMenuOpenChangeEvent) => void | — |
| Callback to invoke when the open state changes. | ||
useContextMenuSub#
| 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. | ||
onOpenChange | (event: useMenuSubOpenChangeEvent) => void | — |
| Callback to invoke when the open state changes. | ||
Accessibility#
See ContextMenu Primitive for WAI-ARIA compliance details and keyboard support.