component

Menu

props · 31 shown · 31 total

Content

  • MenuNode[]

    The menu's content, in render order: a data array of {@link MenuNode}s — actions, links, checkboxes, radio groups, groups, submenus (each with its own nested `items`), separators and custom content blocks. This array is the menu's only content API; there is no child-component composition.

State

  • boolean
    default false

    Whether the menu is open. Bindable in Svelte.

  • readonly string[]
    default []

    The submenu ids drilled into, root first (`submenuMode="drill"` only). Bindable in Svelte (controlled elsewhere with `onPathChange`). Ids that don't name an enabled submenu of the level before them are ignored. Resets to `[]` whenever the menu closes.

  • string
    default ""

    The search query. Bindable in Svelte (controlled elsewhere with `onQueryChange`). Resets to `""` whenever the menu closes.

Appearance

  • "primary" "secondary" "tertiary" "highlight"
    default "secondary"

    How loud a CHECKED row is — the `menuitemcheckbox` / `menuitemradio` items the menu marks as chosen. Same vocabulary as Panel / Navigation / TreeView. `"secondary"` (the default) is the quiet recessed well. `"primary"` fills the row with the accent surface and flips its label and description to the contrast ramp, so the current option in a radio group (a workspace switcher, a sort order) reads at a glance instead of being found by its check mark. `"tertiary"` is the colorless recess. This is the LOUDNESS axis only — {@link MenuBaseProps.activeTone} picks the color.

  • ListBoxActiveTone
    default "inherit"

    Which palette a CHECKED row paints with, independent of the list's own palette. Defaults to `"inherit"` (follow the list); set it to split the two apart — a plain neutral menu whose current row is brand blue is `activeEmphasis="primary" activeTone="primary"`. Only the filled row reads it, so it pairs with `activeEmphasis="primary"`.

  • "start" "end"
    default "end"

    Which side of the row the checked glyph sits on. `end` (the default) keeps every checkable row's label in the same column as the labels of every other section; `start` puts the check in a leading column instead. Submenus inherit it.

  • "transparent" "surface.peak" "surface.hill" "surface.base" "surface.valley" "surface.ground"
    default "surface.peak"

    Surface ramp step the menu's list paints.

  • "none" "default" "bold" "muted" "accent"
    default "muted"

    Resting border color of the menu's list surface.

  • "sm" "md" "lg" "2xl" "xl" "inherit" "inner" "xs" "none" "2xs" "3xl" "4xl" "5xl" "6xl" "full"
    default "md"

    Corner radius of the menu's list surface. The menu panel sits inside a transparent, unpadded popover `<dialog>`, so the list's own `radius="inner"` would resolve against that dialog's `xl` corner rather than anything meaningful — pass the corner you want explicitly.

  • "sm" "md" "lg" "xl" "xs" "none"

    Elevation of the menu's list surface. Floating menus get `lg` from the listbox recipe's `[data-popover]` rule by default.

  • ListBoxTone
    default "neutral"

    Color palette the menu's list resolves its surfaces and text against. Stays `"neutral"` by default so rows read as plain text. This re-themes the WHOLE list — every row's hover and muted text included. To color only the current row, leave this alone and use {@link MenuBaseProps.activeTone} instead.

  • "soft" "framed" "separate" "plain"
    default "soft"

    How every row's `shortcut` renders (KbdGroup `appearance`). soft: quiet square keys on a subtle fill (the default). framed: one rounded frame per chord holding compact caps. separate: loose caps. plain: text only.

  • boolean
    default true

    Whether checkable rows (`menuitemcheckbox` / `menuitemradio`) draw the checked glyph. On by default, with every row of the same segment reserving the column so nothing shifts when the choice moves. Turn it off when the chosen row already reads as chosen on its own — a filled `activeEmphasis="primary"` row, say — and every label then sits flush instead of paying for an indent. Purely visual: `aria-checked` is unaffected, so the state is still announced.

  • "sm" "md" "lg"
    default "md"

    Visual size.

Layout

  • AnchorPoint null

    Open the menu at a viewport point (client coordinates, e.g. a `contextmenu` event's `clientX` / `clientY`) instead of at its trigger — a right-click menu at the pointer. `placement` applies relative to the point, and the panel still flips / shifts at the viewport edges. Submenus keep opening beside their rows. Set it together with `open`; clear it (`null` / `undefined`) to anchor to the trigger again.

  • 1 2 3 4
    default 1

    Lays the menu's rows out in a grid of this many columns. Columns size to their content (with a floor), every group shares the same columns, and group titles, separators and custom blocks span the full width. Search results stay one column, and flyout submenus are not affected. The arrow keys move through the grid: | Key | Moves to | | --- | --- | | → | the next row on the same line. From the last column: drills into / opens a submenu row's submenu, else stays | | ← | the previous row on the same line. From the first column: goes back a level (drill) / closes a flyout submenu, else stays | | ↓ / ↑ | the same column on the next / previous line, across groups (a shorter line: its last row); stays at the top and bottom | Disabled rows are skipped in the direction of travel. Home / End, typeahead and Enter work as in a one-column menu. In a searchable menu the grid keys apply while the query is empty and a row is highlighted; while typing, the keys behave as in a one-column menu.

  • "top" "right" "bottom" "left" "top-start" "top-end" "right-start" "right-end" "bottom-start" "bottom-end" "left-start" "left-end"
    default "bottom-start"

    Preferred placement of the menu panel relative to its trigger.

Behavior

  • PopoverMountStrategy
    default "lazy"

    When the menu's panel (its popover `<dialog>`, list and submenus) is in the DOM. "lazy" renders only the trigger while closed — a list that puts a menu on every row pays for the trigger alone — mounts the panel when the menu opens, and removes it once it has closed and its exit animation has finished. "keep" mounts it at the first open and keeps it. "eager" keeps it mounted while closed (the pre-lazy behaviour). Submenus follow the same strategy. Under "lazy" / "keep" the trigger's `aria-controls` is only set while the menu is open. Astro always renders the panel on the server, so it ignores this.

  • onOpenChange svelte
    (open: boolean) => void

    Fired when the open state changes.

  • "auto" "mac" "other"
    default "auto"

    Which platform's labels the row shortcuts use (`mod` → ⌘ on mac, Ctrl elsewhere) — also the platform `aria-keyshortcuts` resolves `mod` for. auto: the detected platform (`detectedPlatform`), mac until one is detected.

  • "flyout" "drill"
    default "flyout"

    How submenus open. "flyout": a popover beside its trigger row (the classic cascading menu). "drill": in place — the menu panel's content is replaced by the submenu's items, with a header holding a back button and the level title (a stack of pages, as on touch screens). ArrowRight / Enter drill in, ArrowLeft / Escape (and Backspace in an empty search) go back. A searchable drill menu searches the current level only.

Events

  • (path: string[]) => void

    Fired with the new path when the user drills in or out (and with `[]` when the menu closes).

  • (query: string) => void

    Fired with the new query as the user types (and with `""` when the menu closes or Escape clears it).

Accessibility

  • string

    Accessible label for the menu surface when there is no visible labelling.

  • MenuDrillLabels

    Drill-mode copy: the back button's accessible name ("Back to {label}", "Back" one level deep) and the search placeholder below the root ("Search {label}…").

Slots

  • trigger required slot svelte
    Snippet<[MenuTriggerProps]>

    The disclosure trigger. Receives the merged trigger bag (Popover wiring + the menu's `aria-haspopup` / `aria-expanded`); spread it onto your own element (typically a `<Button>`).

Advanced

  • "mac" "other"

    The viewer's platform, as `detectPlatform()` from `@pindoba/core-kbd` reports it after mount. Used only when `shortcutPlatform` is "auto".

  • id svelte
    string

    Stable id root (auto-generated when omitted).

  • MenuPassThrough

    Per-slot style / attribute escape hatch.

Type

  • Components
  • Blocks