# Context Menu

> Actions for the item under the pointer, opened with right-click on desktop and a long press on touch. Built from the same rows as Menu.

Source: https://ritla.app/ui/context-menu

## Installation

Installing from the registry is coming soon. Until then, these are the commands you will run.

```bash
npx ritla add context-menu
```

With the shadcn CLI instead:

```bash
npx shadcn@latest add @ritla/context-menu
```

Dependencies: `@base-ui/react`, `@phosphor-icons/react`

## Usage

```tsx
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from "@/components/ui/context-menu";

<ContextMenu>
  <ContextMenuTrigger>
    Statement_Sep_2026.pdf
    {/* Also give the row a visible ⋮ button with the same actions: it is the keyboard path. */}
  </ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem leadingIcon={PencilSimpleIcon} shortcut="F2" aria-keyshortcuts="F2">Rename</ContextMenuItem>
    <ContextMenuItem leadingIcon={TrashIcon} danger>Delete file</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>
```

## API reference

### `ContextMenu`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open / defaultOpen / onOpenChange` | `boolean, (open) => void` | None | The open state, if you control it. |
| `children` | `ReactNode` | None | `ContextMenuTrigger` and `ContextMenuContent`. |

### `ContextMenuTrigger`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | None | The area that opens the menu: a row or a card. Keep it out of the tab order and put a visible ⋮ button in it that opens the same actions: that button is the keyboard path. |

### `ContextMenuItem`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` | None | Figma's Title: a verb, two or three words. |
| `leadingIcon` | `IconComponent` | None | Figma's Show leading: a 24px icon at the start. |
| `shortcut` | `ReactNode` | None | The shortcut as printed (⌘D), shown only; pass `aria-keyshortcuts` with it. |
| `danger` | `boolean` | None | The destructive action (Delete): red, last, in its own group. |
| `description` | `ReactNode` | None | A second line under the title. |
| `onClick` | `() => void` | None | Runs the action and closes the menu. |

### `ContextMenuSeparator / ContextMenuGroup / ContextMenuLabel`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `…` | `Menu parts` | None | A divider between groups, a group and a group header, as in Menu. |

## Accessibility

Keyboard (keys as in left-to-right; arrows swap in right-to-left):

- `Tab`: Reaches the row's ⋮ button, not the row itself.
- `Enter` + `Space`: On the ⋮ button: opens the same actions.
- `ArrowDown` + `ArrowUp`: Between the actions.
- `Enter`: Runs the action.
- `Escape`: Closes the menu and returns focus to the button.

ARIA:

- The menu is a `menu` and each action a `menuitem`; it takes its direction and language from the area it opened from.
- A context menu is never the only way to an action: pair it with a visible button (the row's ⋮) that opens the same actions, because many people never right-click and a keyboard can't reach it. The row stays out of the tab order; the button is the keyboard path.
- The destructive action says what it does in its name (“Delete file”), not only with red.

## Arabic and RTL notes

Mirrors:

- In Arabic the menu opens to the left of the pointer, with icons on the right and shortcuts on the left.

Does not mirror:

- The order of the actions.
- Shortcuts keep their Latin form, left to right (⌘D, F2).
- Icons such as Download and Trash.

Numerals: Shortcuts as printed; digits aren't converted.

Arabic typography: 48px rows; title `label-14` Medium; shortcut `label-12` Medium on `container/muted`.

Mixed-direction text: The shortcut is isolated LTR.
