Introducing PrimeReact v11-alpha 🎉Discover Now

useContextMenu

Hooks that manage context menu state, right-click positioning, keyboard navigation, and submenu coordination.

basic-demo

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: useContextMenu for root state, useContextMenuSub for 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)
});

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' });

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#

NameTypeDefault
globalbooleanfalse
Attaches the menu to document instead of a particular element.
openboolean—
Controlled open state of the menu.
defaultOpenbooleanfalse
Default open state for uncontrolled mode.
appendTo"body" | HTMLElement | "self"'body'
The element to which the overlay is appended.
baseZIndexnumber0
Base zIndex value to use in layering.
autoZIndexbooleantrue
Whether to automatically manage layering.
tabIndexnumber0
Index of the element in tabbing order.
onOpenChange(event: useMenuOpenChangeEvent) => void—
Callback to invoke when the open state changes.

useContextMenuSub#

NameTypeDefault
openboolean—
Controlled open state of the submenu.
defaultOpenbooleanfalse
Default open state for uncontrolled mode.
disabledbooleanfalse
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.