

# Menu

Action menu namespace. `Menu` is Root for compound menus; use `Menu.FromSections`, `Menu.ContextMenu`, or `Menu.Overflow` for common presets. The trigger child must forward DOM props — there is no `render` prop.

State attributes, positioner CSS variables, and `onOpenChange` details are documented in [Overlay lifecycle](/docs/overlay-lifecycle).

## Examples

### Compound parts

Compose `Menu.Trigger`, `Menu.Popup`, `Menu.Item`, `Menu.Section`, and `Menu.Separator`.

```tsx
import { Button, Menu } from '@var-ui/react';

<Menu>
  <Menu.Trigger>
    <Button intent="secondary">Song</Button>
  </Menu.Trigger>
  <Menu.Popup>
    <Menu.Item id="lib" onAction={() => {}}>Add to Library</Menu.Item>
    <Menu.Separator />
    <Menu.Section title="Danger">
      <Menu.Item id="delete" onAction={() => {}}>Delete</Menu.Item>
    </Menu.Section>
  </Menu.Popup>
</Menu>
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

### From sections

Pass a `trigger` and `sections` of items (optional section labels, shortcuts, `danger`, `disabled`).

```tsx
import { Button, Menu } from '@var-ui/react';

<Menu.FromSections
  trigger={<Button>Actions</Button>}
  sections={[{ items: [{ id: 'edit', label: 'Edit' }] }]}
/>
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

```tsx
import { Button, Menu } from '@var-ui/react';

<Menu.FromSections
  trigger={<Button intent="secondary">File</Button>}
  sections={[
    {
      label: 'Edit',
      items: [
        { id: 'cut', label: 'Cut', shortcut: '⌘X' },
        { id: 'copy', label: 'Copy', shortcut: '⌘C' },
        { id: 'paste', label: 'Paste', shortcut: '⌘V' },
      ],
    },
    {
      label: 'Danger zone',
      items: [
        { id: 'archive', label: 'Archive' },
        { id: 'delete', label: 'Delete…', danger: true },
      ],
    },
  ]}
/>
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

### Context menu

Wrap a surface and pass `sections`. Right-click (or the platform context-menu gesture) opens the menu at the pointer. The child must be a DOM element `Pressable` can attach a ref to (e.g. a `div`).

```tsx
import { Menu } from '@var-ui/react';

<Menu.ContextMenu sections={[{ items: [{ id: 'copy', label: 'Copy' }] }]}>
  <div>Right-click me</div>
</Menu.ContextMenu>
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

```tsx
import { Menu } from '@var-ui/react';

<Menu.ContextMenu
  sections={[
    {
      label: 'Edit',
      items: [
        { id: 'rename', label: 'Rename' },
        { id: 'duplicate', label: 'Duplicate' },
      ],
    },
    {
      label: 'Clipboard',
      items: [
        { id: 'copy', label: 'Copy' },
        { id: 'paste', label: 'Paste' },
        { id: 'delete', label: 'Delete', danger: true },
      ],
    },
  ]}
>
  <div>Project card — right-click for actions</div>
</Menu.ContextMenu>
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

### Overflow

Icon-only overflow menu using the `moreHorizontal` glyph — same `sections` shape as other presets.

```tsx
import { Menu } from '@var-ui/react';

<Menu.Overflow sections={[{ items: [{ id: 'edit', label: 'Edit' }] }]} />
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

```tsx
import { Menu } from '@var-ui/react';

<Menu.Overflow
  aria-label="Row actions"
  sections={[
    {
      items: [
        { id: 'share', label: 'Share' },
        { id: 'duplicate', label: 'Duplicate' },
        { id: 'archive', label: 'Archive' },
        { id: 'delete', label: 'Delete', danger: true },
      ],
    },
  ]}
/>
```

```astro
<!-- No Astro binding yet — use @var-ui/react -->
```

```html
<!-- No HTML demo yet — use @var-ui/react -->
```

## Props

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| children | ReactNode | no |  |  |
| defaultOpen | boolean \| undefined | no |  |  |
| isOpen | boolean \| undefined | no |  |  |
| onOpenChange | OverlayOpenChangeHandler \| undefined | no |  |  |
| portalContainer | Element \| undefined | no |  | Element the menu portals into instead of `document.body`. Needed when a subtree renders under a different theme than the page ambient. |

## Accessibility

Built on React Aria `MenuTrigger` / `Menu`. Arrow keys move between items, Enter/Space activates, Escape closes. Give destructive items clear labels — visual tone is not enough. For `Menu.ContextMenu`, ensure essential actions are also available without right-click for keyboard-only users.
