Skip to content

Menu

A short list of actions behind a button, usually the row actions on a server or skill.

OverlaysIsland

Examples

Row menu

The default trigger is a small ghost "more" button, named by `label`.

Example
<Menu
  label="Actions for GitHub"
  items={[
    { name: 'test', label: 'Test connection', icon: 'plug-zap' },
    { name: 'rename', label: 'Rename server', icon: 'pencil' },
    { name: 'logs', label: 'View logs', icon: 'activity' },
    { separator: true },
    { name: 'delete', label: 'Delete server', icon: 'trash', tone: 'danger' },
  ]}
/>

Text trigger, checkbox items

Example
<Menu
  label="Show transports"
  trigger={{ text: 'Transports', icon: 'cable' }}
  placement="bottom-start"
  items={[
    { name: 'http', label: 'HTTP', checked: true },
    { name: 'sse', label: 'SSE', checked: true },
    { name: 'stdio', label: 'stdio', checked: false, disabled: true },
  ]}
/>

Usage

Usage
import { Menu } from '@switchboard/ui'

<Menu
  label={`Actions for ${server.name}`}
  items={[
    { name: 'logs', label: 'View logs', icon: 'activity', href: routes.servers.logs.href({ id }) },
    { name: 'pause', label: 'Pause routing', icon: 'route', form: { action: routes.servers.pause.href({ id }) } },
  ]}
/>

Props

Every component also takes mix, for css() and mixins applied after its own style.

Menu

Menu props
PropTypeDefaultDescription
label*string–Accessible name of the menu, and of the icon trigger: "Actions for GitHub".
items*MenuEntry[]–Items, { separator: true } and { heading: string } (a small group label) entries, in order.
trigger{ text?, icon?, variant?, size?, avatar? }–With text: a button with a chevron (secondary). With avatar (a name): a round avatar button (account menus). Otherwise a ghost icon button, more-horizontal by default.
header{ title: string; description?: string }–Non-interactive block over the items: who is signed in.
placementAnchorPlacement'bottom-end'Where the menu opens relative to the trigger.

MenuEntry

MenuEntry props
PropTypeDefaultDescription
name*string–Unique key, sent in the bubbling select event.
label*string–Item text.
iconIconName–Leading icon.
hrefstring–Navigate here when chosen.
form{ action: string; fields?: Record<string, string> }–POST here when chosen; fields become hidden inputs.
tone'danger'–Red text and highlight, for destructive items.
disabledboolean–Shown but not choosable.
shortcutstring–Hint on the right, e.g. "⌘D".
checkedboolean–Makes it a checkbox item; shows a check when true.
radioboolean–With checked: a radio item (menuitemradio), e.g. the Theme group in the account menu.

Accessibility

  • The trigger is a button with aria-haspopup and aria-expanded; the list has role="menu" and items role="menuitem" (menuitemcheckbox when checked is set).
  • Arrow keys move, Home/End jump, typing a letter jumps to an item, Enter or Space chooses.
  • Escape and clicks outside close it and return focus to the trigger.

Guidance

Do

  • Name the menu after its object: "Actions for GitHub".
  • Put destructive items last, after a separator.

Don’t

  • Hide the only way to do a common task in a menu; make it a button.
  • Put more than about seven items or nested menus in one.