# Context Menu (/docs/context-menu)





## API Reference [#api-reference]

<BaseUIReference href="https://base-ui.com/react/components/context-menu" />

## Basic [#basic]

<Preview cssProperties="contextMenuPlaygroundCssProperties">
  <ContextMenuExample />

  <Preview.Code>
    {`
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuContent,
            ContextMenuItem,
            ContextMenuSeparator,
            ContextMenuTrigger,
          } from "moduix";

          export function ContextMenuDemo() {
            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent>
                  <ContextMenuArrow />
                  <ContextMenuItem closeOnClick>Add to Library</ContextMenuItem>
                  <ContextMenuItem closeOnClick>Add to Playlist</ContextMenuItem>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick>Play Next</ContextMenuItem>
                  <ContextMenuItem closeOnClick>Play Last</ContextMenuItem>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick disabled>
                    Share
                  </ContextMenuItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>

  <Preview.CSSProperties>
    {(context) => <ContextMenuCssPropertiesPanel {...context} />}
  </Preview.CSSProperties>

  <Preview.CSSPlayground>
    {(context) => <ContextMenuCssPlaygroundPanel {...context} />}
  </Preview.CSSPlayground>
</Preview>

## Anatomy [#anatomy]

Context menu is composed from a trigger surface and a popup content layer. Keep interactive parts
inside `ContextMenuContent` so keyboard navigation, roving focus, and close behavior stay managed by
the root state machine.

```text
ContextMenu
├─ ContextMenuTrigger
└─ ContextMenuContent
   ├─ ContextMenuArrow
   ├─ ContextMenuItem
   ├─ ContextMenuSeparator
   └─ ContextMenuSubmenu
      ├─ ContextMenuSubmenuTrigger
      │  └─ ContextMenuSubmenuTriggerIcon
      └─ ContextMenuSubmenuContent
         └─ ContextMenuItem
```

```tsx
<ContextMenu>
  <ContextMenuTrigger>Right click here</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuArrow />
    <ContextMenuItem closeOnClick>Open</ContextMenuItem>
    <ContextMenuSubmenu>
      <ContextMenuSubmenuTrigger>
        Share
        <ContextMenuSubmenuTriggerIcon />
      </ContextMenuSubmenuTrigger>
      <ContextMenuSubmenuContent>
        <ContextMenuItem closeOnClick>Copy link</ContextMenuItem>
      </ContextMenuSubmenuContent>
    </ContextMenuSubmenu>
  </ContextMenuContent>
</ContextMenu>
```

| Part                           | Role                                                                                                   |
| ------------------------------ | ------------------------------------------------------------------------------------------------------ |
| `ContextMenu`                  | Root state machine. Handles open state, focus management, and close interactions.                      |
| `ContextMenuTrigger`           | Surface that opens the menu on context interaction (right click or long press).                        |
| `ContextMenuContent`           | Popup container for menu items. Accepts positioning props and renders service layers internally.       |
| `ContextMenuArrow`             | Optional visual pointer from popup to trigger location.                                                |
| `ContextMenuItem`              | Action row. Supports disabled state and `closeOnClick` behavior.                                       |
| `ContextMenuLinkItem`          | Link row for navigation while preserving context menu focus and highlight behavior.                    |
| `ContextMenuSeparator`         | Visual divider between related item groups.                                                            |
| `ContextMenuSubmenu*`          | Nested branch for secondary actions (`Trigger`, `TriggerIcon`, and `Content`).                         |
| `ContextMenuGroup*` / controls | Optional structured controls: labels, radio groups/items, checkbox items, and related indicator slots. |

`ContextMenuContent` uses internal service slots (`portal`, optional `backdrop`, `positioner`, `popup`).
In most cases, keep the default structure and style visible parts such as trigger, items, separators, and
arrow. Use `classNames`, `portalProps`, `positionerProps`, `backdropProps`, and `withBackdrop` when you
need slot-level customization.

## Composition [#composition]

Pass positioning props such as `sideOffset`, `align`, `collisionPadding`, and `positionMethod`
directly to `ContextMenuContent`.

`className` styles the visible popup. `classNames` styles the internal service slots hidden from
the default composition. Use `container`, `portalProps`, `backdropProps`, `positionerProps`, and
`withBackdrop` when you need the matching Base UI escape hatches:

```tsx
<ContextMenuContent
  className={styles.popup}
  classNames={{
    portal: styles.portal,
    backdrop: styles.backdrop,
    positioner: styles.positioner,
  }}
  withBackdrop
/>
```

## Examples [#examples]

### Nested [#nested]

Use `ContextMenuSubmenu` with `ContextMenuSubmenuTrigger` and `ContextMenuSubmenuContent` for nested actions.

<Preview>
  <NestedContextMenuExample />

  <Preview.Code>
    {`
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuContent,
            ContextMenuItem,
            ContextMenuSeparator,
            ContextMenuSubmenu,
            ContextMenuSubmenuContent,
            ContextMenuSubmenuTrigger,
            ContextMenuSubmenuTriggerIcon,
            ContextMenuTrigger,
          } from "moduix";

          export function NestedContextMenuDemo() {
            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent>
                  <ContextMenuArrow />
                  <ContextMenuItem closeOnClick>Add to Library</ContextMenuItem>
                  <ContextMenuSubmenu>
                    <ContextMenuSubmenuTrigger>
                      Add to Playlist
                      <ContextMenuSubmenuTriggerIcon />
                    </ContextMenuSubmenuTrigger>
                    <ContextMenuSubmenuContent>
                      <ContextMenuItem closeOnClick>Get Up!</ContextMenuItem>
                      <ContextMenuItem closeOnClick>Inside Out</ContextMenuItem>
                      <ContextMenuItem closeOnClick>Night Beats</ContextMenuItem>
                      <ContextMenuSeparator />
                      <ContextMenuItem closeOnClick>New Playlist...</ContextMenuItem>
                    </ContextMenuSubmenuContent>
                  </ContextMenuSubmenu>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick>Favorite</ContextMenuItem>
                  <ContextMenuItem closeOnClick>Share</ContextMenuItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Shortcuts [#shortcuts]

Use `ContextMenuItemShortcut` for keyboard shortcut text instead of reserving extra item padding.

<Preview>
  <ShortcutsContextMenuExample />

  <Preview.Code>
    {`
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuContent,
            ContextMenuItem,
            ContextMenuItemShortcut,
            ContextMenuSeparator,
            ContextMenuTrigger,
          } from "moduix";

          export function ShortcutsContextMenuDemo() {
            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent>
                  <ContextMenuArrow />
                  <ContextMenuItem closeOnClick>
                    Copy
                    <ContextMenuItemShortcut>Ctrl+C</ContextMenuItemShortcut>
                  </ContextMenuItem>
                  <ContextMenuItem closeOnClick>
                    Paste
                    <ContextMenuItemShortcut>Ctrl+V</ContextMenuItemShortcut>
                  </ContextMenuItem>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick>
                    Rename
                    <ContextMenuItemShortcut>F2</ContextMenuItemShortcut>
                  </ContextMenuItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Groups And Controls [#groups-and-controls]

Use groups, radio items, and checkbox items when the menu changes application state.

<Preview>
  <GroupsAndControlsContextMenuExample />

  <Preview.Code>
    {`
          import { useState } from "react";
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuCheckboxItem,
            ContextMenuCheckboxItemIndicator,
            ContextMenuContent,
            ContextMenuGroup,
            ContextMenuGroupLabel,
            ContextMenuItemText,
            ContextMenuRadioGroup,
            ContextMenuRadioItem,
            ContextMenuRadioItemIndicator,
            ContextMenuSeparator,
            ContextMenuTrigger,
          } from "moduix";

          export function GroupsAndControlsContextMenuDemo() {
            const [sortBy, setSortBy] = useState("date");
            const [showMinimap, setShowMinimap] = useState(true);
            const [showSearch, setShowSearch] = useState(true);
            const [showSidebar, setShowSidebar] = useState(false);

            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent>
                  <ContextMenuArrow />
                  <ContextMenuGroup>
                    <ContextMenuGroupLabel>Sort</ContextMenuGroupLabel>
                    <ContextMenuRadioGroup value={sortBy} onValueChange={setSortBy}>
                      <ContextMenuRadioItem value="date">
                        <ContextMenuRadioItemIndicator />
                        <ContextMenuItemText>Date</ContextMenuItemText>
                      </ContextMenuRadioItem>
                      <ContextMenuRadioItem value="name">
                        <ContextMenuRadioItemIndicator />
                        <ContextMenuItemText>Name</ContextMenuItemText>
                      </ContextMenuRadioItem>
                      <ContextMenuRadioItem value="type">
                        <ContextMenuRadioItemIndicator />
                        <ContextMenuItemText>Type</ContextMenuItemText>
                      </ContextMenuRadioItem>
                    </ContextMenuRadioGroup>
                  </ContextMenuGroup>
                  <ContextMenuSeparator />
                  <ContextMenuGroup>
                    <ContextMenuGroupLabel>Workspace</ContextMenuGroupLabel>
                    <ContextMenuCheckboxItem checked={showMinimap} onCheckedChange={setShowMinimap}>
                      <ContextMenuCheckboxItemIndicator />
                      <ContextMenuItemText>Minimap</ContextMenuItemText>
                    </ContextMenuCheckboxItem>
                    <ContextMenuCheckboxItem checked={showSearch} onCheckedChange={setShowSearch}>
                      <ContextMenuCheckboxItemIndicator />
                      <ContextMenuItemText>Search</ContextMenuItemText>
                    </ContextMenuCheckboxItem>
                    <ContextMenuCheckboxItem checked={showSidebar} onCheckedChange={setShowSidebar}>
                      <ContextMenuCheckboxItemIndicator />
                      <ContextMenuItemText>Sidebar</ContextMenuItemText>
                    </ContextMenuCheckboxItem>
                  </ContextMenuGroup>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Indicator Right With Icon [#indicator-right-with-icon]

Use `indicator="end"` to align checkbox and radio indicators to the end. Item text slots and icon slots accept custom content and `className`.

<Preview>
  <IndicatorRightContextMenuExample />

  <Preview.Code>
    {`
          import { useState } from "react";
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuCheckboxItem,
            ContextMenuCheckboxItemIndicator,
            ContextMenuContent,
            ContextMenuItemText,
            ContextMenuItemTextContent,
            ContextMenuItemTextIcon,
            ContextMenuItemTextLabel,
            ContextMenuTrigger,
            InfoIcon,
            ShareIcon,
          } from "moduix";

          export function IndicatorRightContextMenuDemo() {
            const [showMinimap, setShowMinimap] = useState(true);
            const [showSearch, setShowSearch] = useState(true);

            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent>
                  <ContextMenuArrow />
                  <ContextMenuCheckboxItem
                    checked={showMinimap}
                    onCheckedChange={setShowMinimap}
                    indicator="end"
                  >
                    <ContextMenuItemText>
                      <ContextMenuItemTextContent>
                        <ContextMenuItemTextIcon>
                          <InfoIcon />
                        </ContextMenuItemTextIcon>
                        <ContextMenuItemTextLabel>Minimap</ContextMenuItemTextLabel>
                      </ContextMenuItemTextContent>
                    </ContextMenuItemText>
                    <ContextMenuCheckboxItemIndicator />
                  </ContextMenuCheckboxItem>
                  <ContextMenuCheckboxItem
                    checked={showSearch}
                    onCheckedChange={setShowSearch}
                    indicator="end"
                  >
                    <ContextMenuItemText>
                      <ContextMenuItemTextContent>
                        <ContextMenuItemTextIcon>
                          <ShareIcon />
                        </ContextMenuItemTextIcon>
                        <ContextMenuItemTextLabel>Search</ContextMenuItemTextLabel>
                      </ContextMenuItemTextContent>
                    </ContextMenuItemText>
                    <ContextMenuCheckboxItemIndicator />
                  </ContextMenuCheckboxItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Positioning [#positioning]

Pass positioning props to `ContextMenuContent`. It renders the portal and positioner internally.

<Preview>
  <PositionedContextMenuExample />

  <Preview.Code>
    {`
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuContent,
            ContextMenuItem,
            ContextMenuSeparator,
            ContextMenuTrigger,
          } from "moduix";

          export function PositionedContextMenuDemo() {
            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent align="start" sideOffset={12} collisionPadding={16}>
                  <ContextMenuArrow />
                  <ContextMenuItem closeOnClick>Open</ContextMenuItem>
                  <ContextMenuItem closeOnClick>Duplicate</ContextMenuItem>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick>Archive</ContextMenuItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Link Items [#link-items]

Use `ContextMenuLinkItem` for navigation actions that should render as links.

<Preview>
  <LinkItemsContextMenuExample />

  <Preview.Code>
    {`
          import {
            ContextMenu,
            ContextMenuArrow,
            ContextMenuContent,
            ContextMenuItem,
            ContextMenuLinkItem,
            ContextMenuSeparator,
            ContextMenuTrigger,
          } from "moduix";

          export function LinkItemsContextMenuDemo() {
            return (
              <ContextMenu>
                <ContextMenuTrigger>Right click here</ContextMenuTrigger>
                <ContextMenuContent>
                  <ContextMenuArrow />
                  <ContextMenuLinkItem href="#projects">Projects</ContextMenuLinkItem>
                  <ContextMenuLinkItem href="#teams">Teams</ContextMenuLinkItem>
                  <ContextMenuLinkItem href="#billing">Billing</ContextMenuLinkItem>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick>Copy Link</ContextMenuItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Custom Styles [#custom-styles]

Use `className` for the popup and `classNames` for internal service slots. Set `withBackdrop` when the menu should render a backdrop.

<Preview>
  <CustomStylesContextMenuExample />

  <Preview.Code>
    {`
          import {
            ContextMenu,
            ContextMenuContent,
            ContextMenuItem,
            ContextMenuSeparator,
            ContextMenuTrigger,
          } from "moduix";

          export function CustomStylesContextMenuDemo() {
            return (
              <ContextMenu>
                <ContextMenuTrigger className={styles.customTrigger}>Right click card</ContextMenuTrigger>
                <ContextMenuContent
                  className={styles.customPopup}
                  classNames={{
                    portal: styles.customPortal,
                    backdrop: styles.customBackdrop,
                    positioner: styles.customPositioner,
                  }}
                  withBackdrop
                >
                  <ContextMenuItem closeOnClick>Open details</ContextMenuItem>
                  <ContextMenuItem closeOnClick>Copy link</ContextMenuItem>
                  <ContextMenuSeparator />
                  <ContextMenuItem closeOnClick disabled>
                    Delete
                  </ContextMenuItem>
                </ContextMenuContent>
              </ContextMenu>
            );
          }
        `}
  </Preview.Code>

  <Preview.CSS>
    {`
          .customTrigger {
            min-width: 14rem;
            min-height: 9rem;
            border-color: var(--color-primary);
            background:
              linear-gradient(var(--color-background), var(--color-background)) padding-box,
              linear-gradient(135deg, var(--color-primary), var(--color-ring)) border-box;
          }

          .customPortal {
            position: relative;
          }

          .customBackdrop {
            background-color: rgb(0 0 0 / 0.08);
            backdrop-filter: blur(0.125rem);
          }

          .customPositioner {
            z-index: var(--z-popup);
          }

          .customPopup {
            --context-menu-popup-min-width: 13rem;
            --context-menu-popup-bg: var(--color-background);
            --context-menu-popup-border-color: var(--color-primary);
            --context-menu-popup-shadow: var(--shadow-lg);
            --context-menu-highlight-bg: var(--color-primary);
            --context-menu-highlight-color: var(--color-primary-foreground);
            --context-menu-separator-color: var(--color-primary);
          }
        `}
  </Preview.CSS>
</Preview>
