Skip to content

Menu

A list of actions opened from a button. Arrow keys move, type-ahead jumps, Esc closes and returns focus.

  • Free core, MIT
  • Version 2.0.0-rc.1
  • APG pattern: Menu button + menu

Examples

These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.

Default

Show the code

Default, code

const Actions = ({ open }: { open?: boolean }) => (
  <MenuTrigger defaultOpen={open}>
    <Button variant="outline">Actions</Button>
    <Menu>
      <MenuItem id="edit" icon={Pencil} shortcut="E">Edit</MenuItem>
      <MenuItem id="duplicate" icon={Copy}>Duplicate</MenuItem>
      <MenuItem id="share" icon={UserPlus} description="Invite people by email">Share</MenuItem>
      <MenuSeparator />
      <MenuItem id="delete" icon={Trash2} tone="destructive">Delete</MenuItem>
    </Menu>
  </MenuTrigger>
);

<Actions />

Open

Show the code

Open, code

const Actions = ({ open }: { open?: boolean }) => (
  <MenuTrigger defaultOpen={open}>
    <Button variant="outline">Actions</Button>
    <Menu>
      <MenuItem id="edit" icon={Pencil} shortcut="E">Edit</MenuItem>
      <MenuItem id="duplicate" icon={Copy}>Duplicate</MenuItem>
      <MenuItem id="share" icon={UserPlus} description="Invite people by email">Share</MenuItem>
      <MenuSeparator />
      <MenuItem id="delete" icon={Trash2} tone="destructive">Delete</MenuItem>
    </Menu>
  </MenuTrigger>
);

<Actions open />

From an icon button

Show the code

From an icon button, code

<MenuTrigger>
  <IconButton icon={Ellipsis} label="More actions for Tom Ellis" variant="ghost" />
  <Menu>
    <MenuItem id="role">Change role</MenuItem>
    <MenuItem id="resend">Resend invite</MenuItem>
    <MenuItem id="remove" tone="destructive">Remove from team</MenuItem>
  </Menu>
</MenuTrigger>

Sections

Show the code

Sections, code

<MenuTrigger defaultOpen>
  <Button variant="outline">View</Button>
  <Menu selectionMode="single" defaultSelectedKeys={['comfortable']}>
    <MenuSection title="Density">
      <MenuItem id="comfortable">Comfortable</MenuItem>
      <MenuItem id="compact">Compact</MenuItem>
    </MenuSection>
    <MenuSeparator />
    <MenuSection title="Sort">
      <MenuItem id="name">By name</MenuItem>
      <MenuItem id="date">By date added</MenuItem>
    </MenuSection>
  </Menu>
</MenuTrigger>

Submenu

Show the code

Submenu, code

<MenuTrigger>
  <Button variant="outline">Move</Button>
  <Menu>
    <MenuItem id="top">To the top</MenuItem>
    <SubmenuTrigger>
      <MenuItem id="folder">To a folder</MenuItem>
      <Menu aria-label="Folders">
        <MenuItem id="design">Design</MenuItem>
        <MenuItem id="research">Research</MenuItem>
      </Menu>
    </SubmenuTrigger>
  </Menu>
</MenuTrigger>

Tokens

The 10 design tokens Menu reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.

Show all 10 tokens
Tokens Menu reads
TokenValue nowCSS variable
color.border.subtle…--sd-color-border-subtle
color.icon.danger…--sd-color-icon-danger
color.icon.default…--sd-color-icon-default
color.text.danger…--sd-color-text-danger
color.text.disabled…--sd-color-text-disabled
color.text.secondary…--sd-color-text-secondary
listbox.check…--sd-listbox-check
listbox.padding…--sd-listbox-padding
spacing.inset.md…--sd-spacing-inset-md
spacing.inset.sm…--sd-spacing-inset-sm

Install

The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).

Install

npm i @superduperui/react @superduperui/tokens

Import

import { Menu, MenuItem, MenuSection, MenuSeparator, MenuTrigger, SubmenuTrigger } from "@superduperui/react"

Props

Menu also takes the props of the React Aria component it’s built on.

Menu props
PropTypeWhat it does
childrenrequiredReactNode | ((item: T) => ReactNode)MenuItem, MenuSection and MenuSeparator elements, or a render function for `items`.
placementPopoverPlacement | 'bottom start' | 'bottom end' | 'top start' | 'top end'Side of the trigger the menu opens on. Default bottom start (submenus open at the end).

When to use it

Use it for

  • Row actions in a table or list (Edit, Duplicate, Delete)
  • More actions than fit in a toolbar
  • Checkable view options (density, sort)

Use something else for

  • Choosing a value for a form: use Select or Combobox
  • Site navigation: use Navbar or Sidebar (not role=menu)
  • One or two actions: show Buttons

Accessibility

Screen readers announce "Actions, menu button, collapsed" then "Edit, menu item, 1 of 4".

WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.1.3, 2.3.2, 2.4.13, 2.5.5, 2.5.6, 2.3.3.

Compact density meets AA (items 32px, 2.5.8), not AAA.

What your product still has to do

  • Confirm or allow undo for destructive items
  • Wire any shortcut you show; the menu only displays it

Shared patterns it ships with: 3.3.6 (destructive items pair with AlertDialog or undo).

This release’s test results

Test results for Menu in this release
axe-core (WCAG A, AA, AAA and best practice)120 runs across every story, theme, density and width: 0 violations
Rendered text contrast180 text runs: 0 below 7:1, lowest 8.43:1
Target size26 targets: 0 under 44px in Comfortable
Focus appearance (2.4.13)18 focus stops in 3 browser engines: all pass
Keyboard scriptChromium 9 of 9, Firefox 9 of 9, WebKit 9 of 9

Manual passes with VoiceOver and NVDA haven’t been done yet.

Keyboard

Each step is scripted and run in Chromium, Firefox and WebKit.

Menu keyboard steps
KeyWhat happens
TabTab reaches the menu button
EnterEnter opens the menu on the first item
ArrowDownDown moves to the next item
EndEnd moves to the last item
HomeHome moves to the first item
Type-ahead moves to the first match
EscapeEsc closes and returns focus to the button
ArrowUpUp on the button opens the menu on the last item
EnterEnter activates the item, closes the menu and returns focus

In Figma

The Figma component is Menu, with Selection (None, Single, Multiple); Width (Medium, Small, Large). The Figma library isn’t published yet.

Figma to code: Selection → selectionMode (None, Single = "single", Multiple = "multiple"); Items → children; Width (Medium, Small, Large; preview only).