# Menu

> An action menu from a button: groups, headings, separators, icons, links and danger items, in a frosted popover.

Category: Overlays. Docs page: https://rime.mjsons.net/components/menu

## Installation

```bash
npx shadcn@latest add KezLahd/rime/menu
```

Menu lists actions (not choices; that is Select). Items can be links (rendered as Next Links) or callbacks, carry an icon and a description, and be marked danger or disabled. It shares Select's popover family.

## Usage

```tsx
import { Menu } from "@/components/ui";

<Menu label="Actions" items={[{ id: "edit", label: "Edit", onSelect: edit }, { id: "sep", separator: true }, { id: "void", label: "Void invoice", tone: "danger", onSelect: confirm }]} />
```

## Props: Menu

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` (required) | `ReactNode` |  | Trigger content. A chevron is appended unless iconOnly or hideChevron. |
| `aria-label` | `string` |  | Accessible name when the trigger content is not descriptive (an avatar, an icon). |
| `items` (required) | `ReadonlyArray<MenuEntry>` |  |  |
| `header` | `ReactNode` |  | Tinted block at the top of the menu: name and ID number, say. |
| `align` | `"start" \| "end"` | `"end"` |  |
| `iconOnly` | `boolean` |  | Icon-only trigger (a "more" ellipsis): a square ghost button, no chevron. Give it an aria-label. |
| `hideChevron` | `boolean` |  | Drops the chevron from a custom trigger that signals the menu another way. |
| `disabled` | `boolean` |  |  |
| `triggerClassName` | `string` |  |  |
| `className` | `string` |  |  |
| `inline` | `boolean` | `false` | Render the menu open, in place, under its trigger: no portal, no focus move, no outside-click listener. For docs and thumbnails. |

## Examples

### Open

inline renders the menu open under its trigger, in place.

```tsx
<Menu inline label="Actions" items={ITEMS} />
```

### Default

```tsx
<Menu label="Actions" items={ITEMS} />
```

## Theme tokens

Per-component tokens. Undeclared by default: the default below is the fallback the CSS uses. Set any of them at :root or on a wrapper to restyle every instance.

| Token | Default |
| --- | --- |
| `--chip-radius` | `var(--r-sm)` |
| `--popover-item-active-bg` | `linear-gradient(to right, rgba(var(--rgb-brand), 0.14), rgba(var(--rgb-brand-deep), 0.07))` |
| `--popover-item-press-bg` | `linear-gradient(to right, rgba(var(--rgb-brand), 0.2), rgba(var(--rgb-brand-deep), 0.1))` |
| `--popover-item-radius` | `var(--r-xs)` |
| `--popover-pad` | `calc(6px * var(--density))` |
| `--popover-radius` | `var(--r-lg)` |
| `--recess-fill-disabled` | `rgba(var(--rgb-white), 0.3)` |

System tokens it reads: `--blur-recess`, `--border-w`, `--brand-gradient-wash`, `--danger-ink`, `--density`, `--dur`, `--dur-fast`, `--ease`, `--ease-out`, `--focus-halo`, `--focus-ring`, `--font-body`, `--ink-body`, `--ink-brand`, `--ink-disabled`, `--ink-heading`, `--ink-muted`, `--ink-secondary`, `--line-soft`, `--popover-blur`, `--popover-border`, `--popover-shadow`, `--popover-surface`, `--r-lg`, `--r-sm`, `--r-xs`, `--recess-fill`, `--recess-fill-hover`, `--rgb-brand`, `--rgb-brand-deep`, `--rgb-contact`, `--rgb-danger`, `--rgb-white`, `--shadow-recess`, `--text-caption`, `--text-micro`, `--text-small`, `--tracking-label`, `--wash-active`, `--wash-subtle`, `--z-popover`.

## Accessibility

- role="menu" with roving focus: arrows, Home, End, typeahead; Esc and Tab close and return focus to the trigger.

## Do

- Put destructive items last, after a separator.

## Don't

- Don't hide the only way to do something important in a menu.
