# components/Menu (zidane-ui)

Import: `import { … } from 'zidane-ui'`. Source: [ui/src/components/Menu.tsx](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx).

## Components

### `Menu`

Component.

Padding + role for a list of rows inside a floating surface; a `menu` / `listbox` handles the
arrow keys.

```ts
function Menu(props: MenuProps): Element
```

**Parameters**

- `props` (`MenuProps`): Component props.

**Returns** `Element`

**Props**

- `aria-label?` (`string`): Accessible name of the list.
- `children` (`ReactNode`): The rows, sections and notes.
- `className?` (`string`): Extra classes on the list element.
- `role?` (`'group' | 'listbox' | 'menu'`, default `'menu'`): The list's ARIA role. `menu` and `listbox` handle arrow, Home, End and first-letter keys;
  `group` does not. Rows take the matching role (`menuitem` or `option`).
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:352](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L352)

### `MenuNote`

Component.

A note, hint or empty state inside a menu: sans, muted, row-aligned.

```ts
function MenuNote(props: MenuNoteProps): Element
```

**Parameters**

- `props` (`MenuNoteProps`): Component props.

**Returns** `Element`

**Props**

- `children` (`ReactNode`): The note text.
- `className?` (`string`): Extra classes on the note.
- `icon?` (`string`): Icon class shown before the text, such as `i-ph-info`.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:405](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L405)

### `MenuRow`

Component.

Renders one row of a menu, list or picker: icon, title, optional description and a trailing
slot. `checked` marks the current choice with a check, `toggle` shows a switch, and `active`
marks the keyboard cursor. Use `render` to draw another element with the row's look. The
ref goes to the `button`.

```ts
const MenuRow: ForwardRefExoticComponent<MenuRowProps & RefAttributes<HTMLButtonElement>>
```

**Props**

- `active?` (`boolean`): Keyboard cursor / hovered-by-nav row.
- `checked?` (`boolean`): The current choice: a check in the trailing slot.
- `description?` (`ReactNode`): Secondary text after the title. Inline it truncates to one line; `size="lg"` stacks it under
  the title, clamped to two lines.
- `descriptionClassName?` (`string`): Applied to the description's own box (e.g. a fade that must hide its ellipsis too).
- `destructive?` (`boolean`, default `false`): Tones the row as dangerous: the title and glyph take the danger colour.
- `hint?` (`string`): Native tooltip (the row's `title` prop is its label).
- `icon?` (`ReactNode`): Leading glyph, drawn muted. Use it only when it means something (a kind, a folder). No icon
  slot renders when omitted.
- `render?` (`(props: MenuRowRenderProps) => ReactElement`): Render another element with the row's look (a link).
- `size?` (`'sm' | 'md' | 'lg'`, default `'md'`): Row density. `lg` stacks the description under the title.
- `title` (`ReactNode`): The row's label.
- `toggle?` (`boolean`): An on/off option: a switch in the trailing slot (use with `role="menuitemcheckbox"`).
- `trailing?` (`ReactNode`): Content at the row's end, such as a keycap or a meta value. A check or switch from `checked` or
  `toggle` follows it.

Source: [ui/src/components/Menu.tsx:115](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L115)

### `MenuSection`

Component.

A labelled group of rows.

```ts
function MenuSection(props: MenuSectionProps): Element
```

**Parameters**

- `props` (`MenuSectionProps`): Component props.

**Returns** `Element`

**Props**

- `children` (`ReactNode`): The rows in the group.
- `className?` (`string`): Extra classes on the group element.
- `label?` (`ReactNode`): Heading above the rows. It names the group.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `trailing?` (`ReactNode`): Content at the end of the heading row, such as a count or an action.

Source: [ui/src/components/Menu.tsx:224](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L224)

### `MenuSeparator`

Component.

Renders a thin rule between groups of rows. In a `listbox` it is drawing only, since a
listbox may hold only options and groups.

```ts
function MenuSeparator(props: MenuSeparatorProps): Element
```

**Parameters**

- `props` (`MenuSeparatorProps`): Component props.

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:255](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L255)

### `MenuSwitch`

Component.

The on/off glyph for an option row or a compact toggle button; the control around it owns the
state.

```ts
function MenuSwitch(props: MenuSwitchProps): Element
```

**Parameters**

- `props` (`MenuSwitchProps`): Component props.

**Returns** `Element`

**Props**

- `className?` (`string`): Extra classes on the root element.
- `on` (`boolean`): Whether the switch is on.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:384](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L384)

## Functions

### `focusMenuRow`

Function.

Focus the row a menu opens on: the current choice, else the first enabled
row. Returns false when there is no row to take focus.

```ts
function focusMenuRow(root: HTMLElement): boolean
```

**Parameters**

- `root` (`HTMLElement`): The element holding the rows.

**Returns** `boolean`

Source: [ui/src/components/Menu.tsx:315](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L315)

### `handleMenuKeyDown`

Function.

Arrow / Home / End / first-letter navigation between the enabled rows
under `event.currentTarget`. Handled keys stop here: the surface is portaled,
and React would otherwise bubble them into the composer behind it.

```ts
function handleMenuKeyDown(event: KeyboardEvent<HTMLElement>): void
```

**Parameters**

- `event` (`KeyboardEvent<HTMLElement>`): The keydown event of the list. Keys typed in a text field, or with Alt, Ctrl or
  Meta held, are ignored.

Source: [ui/src/components/Menu.tsx:286](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L286)

### `useRowHint`

Function.

Explanations for a compact list: the hovered (or focused) row's text, else
`fallback` (the current row's). Spread `bind(text)` on each row and render
the returned text in a `MenuNote` under the list.

```ts
function useRowHint(
  fallback: string | undefined,
): { bind: (text: string | undefined) => { onBlur: () => void; onFocus: () => void; onMouseEnter: () => void; onMouseLeave: () => void }; hint: string | undefined }
```

**Parameters**

- `fallback` (`string | undefined`): The text shown while no row is hovered or focused, usually the current row's.

**Returns** `{ bind: (text: string | undefined) => { onBlur: () => void; onFocus: () => void; onMouseEnter: () => void; onMouseLeave: () => void }; hint: string | undefined }`: `hint`, the text to show, and `bind(text)`, which returns the hover and focus handlers
to spread on a row.

Source: [ui/src/components/Menu.tsx:426](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L426)

## Interfaces

### `MenuNoteProps`

Interface.

Props for [`MenuNote`](https://zidane.si/docs/reference/ui-components-menu.md#MenuNote).

```ts
interface MenuNoteProps
```

**Properties**

- `children` (`ReactNode`): The note text.
- `className?` (`string`): Extra classes on the note.
- `icon?` (`string`): Icon class shown before the text, such as `i-ph-info`.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:389](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L389)

### `MenuProps`

Interface.

Props for [`Menu`](https://zidane.si/docs/reference/ui-components-menu.md#Menu).

```ts
interface MenuProps
```

**Properties**

- `aria-label?` (`string`): Accessible name of the list.
- `children` (`ReactNode`): The rows, sections and notes.
- `className?` (`string`): Extra classes on the list element.
- `role?` (`'group' | 'listbox' | 'menu'`, default `'menu'`): The list's ARIA role. `menu` and `listbox` handle arrow, Home, End and first-letter keys;
  `group` does not. Rows take the matching role (`menuitem` or `option`).
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:329](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L329)

### `MenuRowProps`

Interface.

Props of [`MenuRow`](https://zidane.si/docs/reference/ui-components-menu.md#MenuRow). It also accepts the attributes of a `button`, except `title`.

```ts
interface MenuRowProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title'>
```

**Properties**

- `active?` (`boolean`): Keyboard cursor / hovered-by-nav row.
- `checked?` (`boolean`): The current choice: a check in the trailing slot.
- `description?` (`ReactNode`): Secondary text after the title. Inline it truncates to one line; `size="lg"` stacks it under
  the title, clamped to two lines.
- `descriptionClassName?` (`string`): Applied to the description's own box (e.g. a fade that must hide its ellipsis too).
- `destructive?` (`boolean`, default `false`): Tones the row as dangerous: the title and glyph take the danger colour.
- `hint?` (`string`): Native tooltip (the row's `title` prop is its label).
- `icon?` (`ReactNode`): Leading glyph, drawn muted. Use it only when it means something (a kind, a folder). No icon
  slot renders when omitted.
- `render?` (`(props: MenuRowRenderProps) => ReactElement`): Render another element with the row's look (a link).
- `size?` (`'sm' | 'md' | 'lg'`, default `'md'`): Row density. `lg` stacks the description under the title.
- `title` (`ReactNode`): The row's label.
- `toggle?` (`boolean`): An on/off option: a switch in the trailing slot (use with `role="menuitemcheckbox"`).
- `trailing?` (`ReactNode`): Content at the row's end, such as a keycap or a meta value. A check or switch from `checked` or
  `toggle` follows it.

Source: [ui/src/components/Menu.tsx:49](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L49)

### `MenuRowRenderProps`

Interface.

Props `MenuRowProps.render` receives to spread onto the element it renders.

```ts
interface MenuRowRenderProps
```

**Properties**

- `children` (`ReactNode`): The row's content: icon, title, description and trailing slot.
- `className` (`string`): The row's classes, merged with the caller's `className`.
- `data-active?` (`''`): Set to an empty string while the row is `active`.
- `data-checked?` (`''`): The current choice: where focus lands when the menu opens.
- `data-destructive?` (`''`): Set to an empty string while the row is `destructive`.
- `data-size` (`'sm' | 'md' | 'lg'`): The row's `size`.
- `title?` (`string`): Native tooltip, from the `hint` prop.

Source: [ui/src/components/Menu.tsx:92](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L92)

### `MenuSectionProps`

Interface.

Props for [`MenuSection`](https://zidane.si/docs/reference/ui-components-menu.md#MenuSection).

```ts
interface MenuSectionProps
```

**Properties**

- `children` (`ReactNode`): The rows in the group.
- `className?` (`string`): Extra classes on the group element.
- `label?` (`ReactNode`): Heading above the rows. It names the group.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.
- `trailing?` (`ReactNode`): Content at the end of the heading row, such as a count or an action.

Source: [ui/src/components/Menu.tsx:206](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L206)

### `MenuSeparatorProps`

Interface.

Props for [`MenuSeparator`](https://zidane.si/docs/reference/ui-components-menu.md#MenuSeparator).

```ts
interface MenuSeparatorProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:242](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L242)

### `MenuSwitchProps`

Interface.

Props for [`MenuSwitch`](https://zidane.si/docs/reference/ui-components-menu.md#MenuSwitch).

```ts
interface MenuSwitchProps
```

**Properties**

- `className?` (`string`): Extra classes on the root element.
- `on` (`boolean`): Whether the switch is on.
- `style?` (`CSSProperties`): Inline styles on the root element, merged after the component's own.

Source: [ui/src/components/Menu.tsx:369](https://github.com/Tahul/zidane/blob/main/ui/src/components/Menu.tsx#L369)
