Skip to content

components/Menu

import { … } from 'zidane-ui'ui/src/components/Menu.tsx

Menu: rows, sections, states
MenuRow lg with description, long title
MenuRow as a link, current page
MenuSwitch

Components#

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

TypeScript
function Menu(props: MenuProps): Element
Parameters
NameTypeDescription
propsMenuProps

Component props.

Element
Menu props
NameTypeDefaultDescription
aria-label?string

Accessible name of the list.

childrenReactNode

The rows, sections and notes.

className?string

Extra classes on the list element.

role?'group' | 'listbox' | 'menu''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.

ui/src/components/Menu.tsx:352

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

TypeScript
function MenuNote(props: MenuNoteProps): Element
Parameters
NameTypeDescription
propsMenuNoteProps

Component props.

Element
MenuNote props
NameTypeDescription
childrenReactNode

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.

ui/src/components/Menu.tsx:405

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.

TypeScript
const MenuRow: ForwardRefExoticComponent<MenuRowProps & RefAttributes<HTMLButtonElement>>
MenuRow props
NameTypeDefaultDescription
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?booleanfalse

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''md'

Row density. lg stacks the description under the title.

titleReactNode

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.

ui/src/components/Menu.tsx:115

A labelled group of rows.

TypeScript
function MenuSection(props: MenuSectionProps): Element
Parameters
NameTypeDescription
propsMenuSectionProps

Component props.

Element
MenuSection props
NameTypeDescription
childrenReactNode

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.

ui/src/components/Menu.tsx:224

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

TypeScript
function MenuSeparator(props: MenuSeparatorProps): Element
Parameters
NameTypeDescription
propsMenuSeparatorProps

Component props.

Element
MenuSeparator props
NameTypeDescription
className?string

Extra classes on the root element.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

ui/src/components/Menu.tsx:255

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

TypeScript
function MenuSwitch(props: MenuSwitchProps): Element
Parameters
NameTypeDescription
propsMenuSwitchProps

Component props.

Element
MenuSwitch props
NameTypeDescription
className?string

Extra classes on the root element.

onboolean

Whether the switch is on.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

ui/src/components/Menu.tsx:384

Functions#

focusMenuRowFunction#

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.

TypeScript
function focusMenuRow(root: HTMLElement): boolean
Parameters
NameTypeDescription
rootHTMLElement

The element holding the rows.

boolean

ui/src/components/Menu.tsx:315

handleMenuKeyDownFunction#

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.

TypeScript
function handleMenuKeyDown(event: KeyboardEvent<HTMLElement>): void
Parameters
NameTypeDescription
eventKeyboardEvent<HTMLElement>

The keydown event of the list. Keys typed in a text field, or with Alt, Ctrl or Meta held, are ignored.

ui/src/components/Menu.tsx:286

useRowHintFunction#

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.

TypeScript
function useRowHint(
  fallback: string | undefined,
): { bind: (text: string | undefined) => { onBlur: () => void; onFocus: () => void; onMouseEnter: () => void; onMouseLeave: () => void }; hint: string | undefined }
Parameters
NameTypeDescription
fallbackstring | undefined

The text shown while no row is hovered or focused, usually the current row's.

{ 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.

ui/src/components/Menu.tsx:426

Interfaces#

Props for MenuNote.

TypeScript
interface MenuNoteProps
MenuNoteProps properties
NameTypeDescription
childrenReactNode

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.

ui/src/components/Menu.tsx:389

Props for Menu.

TypeScript
interface MenuProps
MenuProps properties
NameTypeDefaultDescription
aria-label?string

Accessible name of the list.

childrenReactNode

The rows, sections and notes.

className?string

Extra classes on the list element.

role?'group' | 'listbox' | 'menu''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.

ui/src/components/Menu.tsx:329

Props of MenuRow. It also accepts the attributes of a button, except title.

TypeScript
interface MenuRowProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title'>
MenuRowProps properties
NameTypeDefaultDescription
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?booleanfalse

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''md'

Row density. lg stacks the description under the title.

titleReactNode

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.

ui/src/components/Menu.tsx:49

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

TypeScript
interface MenuRowRenderProps
MenuRowRenderProps properties
NameTypeDescription
childrenReactNode

The row's content: icon, title, description and trailing slot.

classNamestring

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.

ui/src/components/Menu.tsx:92

Props for MenuSection.

TypeScript
interface MenuSectionProps
MenuSectionProps properties
NameTypeDescription
childrenReactNode

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.

ui/src/components/Menu.tsx:206

Props for MenuSeparator.

TypeScript
interface MenuSeparatorProps
MenuSeparatorProps properties
NameTypeDescription
className?string

Extra classes on the root element.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

ui/src/components/Menu.tsx:242

Props for MenuSwitch.

TypeScript
interface MenuSwitchProps
MenuSwitchProps properties
NameTypeDescription
className?string

Extra classes on the root element.

onboolean

Whether the switch is on.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

ui/src/components/Menu.tsx:369