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 { 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 — triggerProps intercepts contextmenu events 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 — useContextMenu for root state, useContextMenuSubmenu for per-submenu behavior
  • Typed items — getItemProps({ type }) produces menuitem, checkbox, or radio behavior with matching ARIA
  • Popover integration — appendTo, baseZIndex, and autoZIndex forward to the internal usePopover for 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 });

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", plus data-value, data-focused, data-disabled, data-checked
  • getSubTriggerProps — data-part="subtrigger", plus data-value, data-focused, data-disabled, data-open
  • 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.
openDelaynumber100
The delay in milliseconds before opening the menu when hovering the trigger. Only applies when `openOnHover` is true.
closeDelaynumber0
The delay in milliseconds before closing the menu when the pointer leaves the trigger. Only applies when `openOnHover` is true.
openOnHoverbooleanfalse
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.
contextuseMenuSubmenuExposes—
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.
navigationmenuuseNavigationMenuExposes—
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` .
navigationmenuMenuIdstring—
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#

NameTypeDefault
openboolean—
Controlled open state of the submenu.
defaultOpenbooleanfalse
Default open state for uncontrolled mode.
disabledbooleanfalse
Whether the submenu is disabled.
openDelaynumber100
The delay in milliseconds before opening the submenu when hovering the subtrigger. Only applies when `openOnHover` is true.
closeDelaynumber0
The delay in milliseconds before closing the submenu when the pointer leaves the subtrigger. Only applies when `openOnHover` is true.
openOnHoverbooleantrue
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.