# Context Menu

> A menu opened at the pointer by right-click or long-press.

## Examples

### Basic

As in Menu, `{ separator: true }` draws a line between groups.

```vue
<script setup lang="ts">
const toast = useToast();
const items = [
  { label: "Open", value: "open" },
  { label: "Rename", value: "rename", hint: "F2" },
  { label: "Duplicate", value: "duplicate" },
  { separator: true as const },
  { label: "Move to trash", value: "trash", hint: "⌫" },
];
</script>

<template>
  <UiContextMenu :items="items" @select="(action) => toast.info(`${action}: report.pdf`)">
    <div class="demo-dropzone" tabindex="0">
      <Icon name="copy" />
      <span>report.pdf</span>
      <small>Right-click, long-press, or focus and press Shift+F10</small>
    </div>
  </UiContextMenu>
</template>
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` | `MenuEntry<T>[]` | `[]` | Menu items in order; `{ separator: true }` draws a line between groups. |
| `label` | `string` | — | Accessible name for the menu. Defaults to the `contextMenu` translation. |
| `disabled` | `boolean` | `false` | Leaves the browser's own context menu in place. |
| `open` | `boolean` | `false` | Whether the menu is open. |

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `[value: T]` | An item was activated. |
| `update:open` | `[value: boolean]` | `v-model:open` update. |

| Slot | Props | Description |
| --- | --- | --- |
| `default` | — | The area that opens the menu on right-click, long-press, or Shift+F10. |
| `item` | `{ item: MenuItem<T>; active: boolean; }` | Item content. |

Types:

```ts
export type MenuEntry<T extends SelectValue = SelectValue> = MenuItem<T> | MenuSeparator;

export interface MenuItem<T extends SelectValue = SelectValue> extends SelectOption<T> {
  /** Trailing text, e.g. a shortcut like "⌘S". Render richer content via the `item` slot. */
  hint?: string;
}

export type SelectValue = string | number;

/** A line between groups of menu items. */
export interface MenuSeparator {
  separator: true;
}

export interface SelectOption<T extends SelectValue = SelectValue> {
  label: string;
  value: T;
  disabled?: boolean;
}
```

## Styling

Its items use Menu's styling hooks.

- Parts (`[data-part="…"]`): `context-menu`, `context-menu-anchor`, `menu-list`, `menu-separator`, `menu-item`, `menu-item-label`, `menu-item-hint`
- State attributes: `data-context-menu-open`, `data-menu-index`, `data-menu-active`

## Keyboard

| Keys                       | Action                        |
| -------------------------- | ----------------------------- |
| `Shift` + `F10` / Menu key | Open from the focused element |
| `↓` / `↑`                  | Move between items            |
| `Home` / `End`             | First / last item             |
| Letters                    | Jump to an item by label      |
| `Enter` / `Space`          | Activate                      |
| `Escape`                   | Close and return focus        |

## Accessibility

- Make the area focusable (`tabindex="0"`) so keyboard users can open it.
- Long-press opens it on touch, including iOS Safari, which has no `contextmenu` event.
