Skip to content

Menu

A menu opens from a button or a right click and lists the commands that apply to what people are working on. Picking a command runs it and closes the menu.

When to use it

Use a menu for commands that do not earn a place on the toolbar, such as sending an offer from a candidate's row or moving the row to another group, and for a short setting such as the order of a list.

For a value in a form field, use a select or a combobox, and for a few controls on one item, a popover.

Anatomy

Rows carry text only. A check marks the chosen option and a chevron a submenu, and a shortcut sits at the right end of its row.

Width
200 to 300 px, set by the longest label
Padding around the rows
4 px
--space-1
Corner radius
12 px, rows 8 px
--radius-xl, --radius-lg
Row height
36 px, 44 px on touch screens
Row padding
10 px on each side
Label
13 px on a 20 px line, regular weight
--type-caption, --text
Shortcut
11 px in tabular digits, at least 10 px from the label
--text-muted
Check and chevron
16 px, the check in the brand blue
--brand-blue, --text-muted
Separator
1 px, 4 px above and below
--border-rule

Commands and choices

A command runs and closes the menu. Where one option applies, the chosen one carries a check and a pick closes the menu. Where several apply, a pick toggles its check and the menu stays open, so people can set several in one visit.

Order and groups

Put the most used commands at the top and related ones in one group, with a line between groups and at most three groups. Destructive commands go last, in their own group, in the error ink.

Name a group only when its items do not explain it, as with Sort by. A submenu goes one level deep. When there are dozens of groups to move a row to, a combobox takes its place.

States

The pointer shows as a fill and the keyboard as a ring, so people can tell which one moved. An unavailable command stays in a button menu, faded, so people learn it exists.

Hover
a faint fill in the text color, 6 percent in dark, 5.5 percent in light
Keyboard focus
2 px ring inside the row
--focus-ring
Pressed
darker fill
--glass-fill-active
Unavailable
quieter text at half opacity, no fill, still reachable by keyboard
--text-muted
Destructive
error ink
--error-ink
Trigger while open
control fill
--surface-control

Keyboard

Enter, Space or Down arrow on the trigger
opens on the first command, Up arrow on the last
Arrows, Home, End
move between commands, wrapping at the ends
A letter
next command that starts with it
Enter or Space
runs the command
Right and Left arrows
open and close a submenu
Escape
closes the menu and returns focus to the trigger
Tab
closes the menu and moves on
Shift+F10 or the Menu key
opens the focused row's context menu

Context menu

A right click on a row or a card opens its context menu at the pointer. It lists only what applies to that item, without shortcuts or unavailable commands.

Offer the same commands on the More actions button too, since nobody sees a context menu before opening it. Text fields and links keep the browser's menu.

Content

Start a command with a verb, in sentence case without a full stop, and add the noun when the verb alone could mean two things. Keep its words the same in the menu, on the toolbar and in the context menu.

Permitted

  • Move to group

    It says what happens.

  • Delete last, in its own group

    Harder to hit by accident.

Not permitted

  • An icon in front of each label

    Menus carry text only.

  • Options

    It names no action.

Accessibility

The menu has role menu and takes its name from the trigger, which carries aria-haspopup, aria-expanded and aria-controls. Rows are menuitem, menuitemcheckbox or menuitemradio, with aria-checked on the last two.

NextTooltip

Menu

Lists the commands for an item or a view, and short settings as rows to choose from.

  • Kind: component
  • Page: https://design.werklist.com/components/menu
  • Version: 2.1.2

When to use it

  • Commands that do not earn a place on the toolbar
  • A short setting such as the sort order, as rows where one applies
  • Visible columns or filters, as rows where several apply
  • The context menu of a row or a card

When not to use it

  • A value for a form field: use a select or a combobox
  • A few controls for one item: use a popover
  • A list of destinations: that is navigation
  • A submenu of dozens of entries: open a combobox
  • Leading icons on rows

Anatomy

  • Layer: above the page (--layer-popover)
  • Width: 200 to 300 px from the longest label
  • Padding around rows: 4 px (--space-1)
  • Panel radius: 12 px (--radius-xl)
  • Row radius: 8 px (--radius-lg)
  • Row height: 36 px, 44 px on touch screens
  • Row padding: 10 px each side
  • Label: 13 px on 20 px, weight 400 (--type-caption, --text)
  • Shortcut: 11 px on 16 px, tabular, at the row's end, at least 10 px from the label. Not in context menus (--text-muted)
  • Check: 16 px check at the row's end, in the brand blue (--brand-blue)
  • Submenu chevron: 16 px chevron pointing right, at the row's end (--text-muted)
  • Separator: 1 px with 4 px above and below (--border-rule)
  • Group label: 13 px on 20 px, 10 px inset, sentence case (--type-caption, --text-label)
  • Surface with a mouse: raised fill and shadow. In the dark theme a 1 px top highlight and a 0.5 px ring (--glass-fill-raised, --elevation-3, --glass-highlight, --glass-ring-raised)
  • Surface on a touch screen: opaque, no blur (--surface-1)
  • Maximum height: 70 percent of the window, or the room on its side when that is less. The rows scroll on their own

Variants

  • Command: menuitem. Runs and closes
  • Choose one: menuitemradio in a group. The chosen row carries the check. A pick closes
  • Choose several: menuitemcheckbox. A pick toggles the check and the menu stays open
  • Context menu: Opened at the pointer by a right click, or at the focused row by Shift+F10 or the Menu key. Relevant commands only. Unavailable ones hidden. No shortcuts
  • Submenu: One level, a handful of rows, opens to the side of its row

States

  • Rest: No fill
  • Hover: A fill of the text color at 6 percent in dark, 5.5 percent in light, with a mouse only
  • Keyboard focus: 2 px ring inset in the row (--focus-ring, --focus-ring-width)
  • Pressed: Fill (--glass-fill-active)
  • Unavailable, button menu: Label in muted ink at half opacity, no hover fill, aria-disabled true, still focusable. Full opacity while it holds keyboard focus (--text-muted)
  • Unavailable, context menu: Hidden
  • Checked: The check shows and aria-checked is true (--brand-blue)
  • Trigger open: Control fill and aria-expanded true (--surface-control)
  • Opening: Fades in over 150 ms while it moves 4 px away from the trigger and grows from 98 percent (--duration-fast, --ease-soft)
  • Closing: Reverse over 150 ms (--duration-fast, --ease-standard)

Keyboard

  • Enter, Space or Down arrow on the trigger: Opens, focus on the first row
  • Up arrow on the trigger: Opens, focus on the last row
  • Down arrow, Up arrow: Next or previous row, wrapping
  • Home, End: First or last row
  • A letter: Next row that starts with it
  • Enter or Space: Runs the row, or toggles a checkbox row
  • Right arrow on a submenu row: Opens the submenu on its first row
  • Left arrow or Escape in a submenu: Closes the submenu only
  • Escape: Closes the menu, focus to the trigger
  • Tab: Closes the menu and moves on
  • Shift+F10 or the Menu key: Opens the context menu of the focused row

Accessibility

  • role menu with aria-labelledby the trigger. A context menu takes an aria-label naming the item, such as Actions for Sunita Rai
  • Rows menuitem, menuitemcheckbox or menuitemradio, with aria-checked on the last two. Role separator. A named group is role group with aria-labelledby
  • Trigger and submenu rows: aria-haspopup menu, aria-expanded, aria-controls
  • Focus moves from row to row, so a screen reader reads each row as it is reached
  • A menu holds no form fields
  • Rows 44 px high on touch screens
  • One menu or popover open at a time. Escape closes a submenu before the menu

Content

  • A verb first, sentence case, no full stop
  • The noun follows when the verb alone is ambiguous: Move to group, Send offer
  • The same words for a command in the menu, the toolbar and the context menu
  • No ellipsis. The dialog that opens carries its own title
  • Destructive commands last, in their own group

Tokens

  • --layer-popover
  • --glass-fill-raised
  • --glass-ring-raised
  • --elevation-3
  • --surface-1
  • --surface-control
  • --radius-xl
  • --radius-lg
  • --space-1
  • --space-2
  • --type-caption
  • --text
  • --text-muted
  • --text-label
  • --brand-blue
  • --error-ink
  • --border-rule
  • --glass-highlight
  • --glass-fill-active
  • --focus-ring
  • --focus-ring-width
  • --duration-fast
  • --ease-soft
  • --ease-standard

JSON

{
  "title": "Menu",
  "path": "/components/menu",
  "url": "https://design.werklist.com/components/menu",
  "text": "https://design.werklist.com/agent/components/menu",
  "summary": "A menu lists the commands for an item or a view and closes as soon as one is picked.",
  "version": "2.1.2",
  "kind": "component",
  "name": "Menu",
  "purpose": "Lists the commands for an item or a view, and short settings as rows to choose from.",
  "use": [
    "Commands that do not earn a place on the toolbar",
    "A short setting such as the sort order, as rows where one applies",
    "Visible columns or filters, as rows where several apply",
    "The context menu of a row or a card"
  ],
  "avoid": [
    "A value for a form field: use a select or a combobox",
    "A few controls for one item: use a popover",
    "A list of destinations: that is navigation",
    "A submenu of dozens of entries: open a combobox",
    "Leading icons on rows"
  ],
  "anatomy": [
    {
      "part": "Layer",
      "measure": "above the page",
      "token": "--layer-popover"
    },
    {
      "part": "Width",
      "measure": "200 to 300 px from the longest label"
    },
    {
      "part": "Padding around rows",
      "measure": "4 px",
      "token": "--space-1"
    },
    {
      "part": "Panel radius",
      "measure": "12 px",
      "token": "--radius-xl"
    },
    {
      "part": "Row radius",
      "measure": "8 px",
      "token": "--radius-lg"
    },
    {
      "part": "Row height",
      "measure": "36 px, 44 px on touch screens"
    },
    {
      "part": "Row padding",
      "measure": "10 px each side"
    },
    {
      "part": "Label",
      "measure": "13 px on 20 px, weight 400",
      "token": "--type-caption, --text"
    },
    {
      "part": "Shortcut",
      "measure": "11 px on 16 px, tabular, at the row's end, at least 10 px from the label. Not in context menus",
      "token": "--text-muted"
    },
    {
      "part": "Check",
      "measure": "16 px check at the row's end, in the brand blue",
      "token": "--brand-blue"
    },
    {
      "part": "Submenu chevron",
      "measure": "16 px chevron pointing right, at the row's end",
      "token": "--text-muted"
    },
    {
      "part": "Separator",
      "measure": "1 px with 4 px above and below",
      "token": "--border-rule"
    },
    {
      "part": "Group label",
      "measure": "13 px on 20 px, 10 px inset, sentence case",
      "token": "--type-caption, --text-label"
    },
    {
      "part": "Surface with a mouse",
      "measure": "raised fill and shadow. In the dark theme a 1 px top highlight and a 0.5 px ring",
      "token": "--glass-fill-raised, --elevation-3, --glass-highlight, --glass-ring-raised"
    },
    {
      "part": "Surface on a touch screen",
      "measure": "opaque, no blur",
      "token": "--surface-1"
    },
    {
      "part": "Maximum height",
      "measure": "70 percent of the window, or the room on its side when that is less. The rows scroll on their own"
    }
  ],
  "variants": [
    {
      "name": "Command",
      "use": "menuitem. Runs and closes"
    },
    {
      "name": "Choose one",
      "use": "menuitemradio in a group. The chosen row carries the check. A pick closes"
    },
    {
      "name": "Choose several",
      "use": "menuitemcheckbox. A pick toggles the check and the menu stays open"
    },
    {
      "name": "Context menu",
      "use": "Opened at the pointer by a right click, or at the focused row by Shift+F10 or the Menu key. Relevant commands only. Unavailable ones hidden. No shortcuts"
    },
    {
      "name": "Submenu",
      "use": "One level, a handful of rows, opens to the side of its row"
    }
  ],
  "states": [
    {
      "name": "Rest",
      "change": "No fill"
    },
    {
      "name": "Hover",
      "change": "A fill of the text color at 6 percent in dark, 5.5 percent in light, with a mouse only"
    },
    {
      "name": "Keyboard focus",
      "change": "2 px ring inset in the row",
      "tokens": [
        "--focus-ring",
        "--focus-ring-width"
      ]
    },
    {
      "name": "Pressed",
      "change": "Fill",
      "tokens": [
        "--glass-fill-active"
      ]
    },
    {
      "name": "Unavailable, button menu",
      "change": "Label in muted ink at half opacity, no hover fill, aria-disabled true, still focusable. Full opacity while it holds keyboard focus",
      "tokens": [
        "--text-muted"
      ]
    },
    {
      "name": "Unavailable, context menu",
      "change": "Hidden"
    },
    {
      "name": "Checked",
      "change": "The check shows and aria-checked is true",
      "tokens": [
        "--brand-blue"
      ]
    },
    {
      "name": "Trigger open",
      "change": "Control fill and aria-expanded true",
      "tokens": [
        "--surface-control"
      ]
    },
    {
      "name": "Opening",
      "change": "Fades in over 150 ms while it moves 4 px away from the trigger and grows from 98 percent",
      "tokens": [
        "--duration-fast",
        "--ease-soft"
      ]
    },
    {
      "name": "Closing",
      "change": "Reverse over 150 ms",
      "tokens": [
        "--duration-fast",
        "--ease-standard"
      ]
    }
  ],
  "keys": [
    {
      "key": "Enter, Space or Down arrow on the trigger",
      "action": "Opens, focus on the first row"
    },
    {
      "key": "Up arrow on the trigger",
      "action": "Opens, focus on the last row"
    },
    {
      "key": "Down arrow, Up arrow",
      "action": "Next or previous row, wrapping"
    },
    {
      "key": "Home, End",
      "action": "First or last row"
    },
    {
      "key": "A letter",
      "action": "Next row that starts with it"
    },
    {
      "key": "Enter or Space",
      "action": "Runs the row, or toggles a checkbox row"
    },
    {
      "key": "Right arrow on a submenu row",
      "action": "Opens the submenu on its first row"
    },
    {
      "key": "Left arrow or Escape in a submenu",
      "action": "Closes the submenu only"
    },
    {
      "key": "Escape",
      "action": "Closes the menu, focus to the trigger"
    },
    {
      "key": "Tab",
      "action": "Closes the menu and moves on"
    },
    {
      "key": "Shift+F10 or the Menu key",
      "action": "Opens the context menu of the focused row"
    }
  ],
  "accessibility": [
    "role menu with aria-labelledby the trigger. A context menu takes an aria-label naming the item, such as Actions for Sunita Rai",
    "Rows menuitem, menuitemcheckbox or menuitemradio, with aria-checked on the last two. Role separator. A named group is role group with aria-labelledby",
    "Trigger and submenu rows: aria-haspopup menu, aria-expanded, aria-controls",
    "Focus moves from row to row, so a screen reader reads each row as it is reached",
    "A menu holds no form fields",
    "Rows 44 px high on touch screens",
    "One menu or popover open at a time. Escape closes a submenu before the menu"
  ],
  "content": [
    "A verb first, sentence case, no full stop",
    "The noun follows when the verb alone is ambiguous: Move to group, Send offer",
    "The same words for a command in the menu, the toolbar and the context menu",
    "No ellipsis. The dialog that opens carries its own title",
    "Destructive commands last, in their own group"
  ],
  "tokens": [
    "--layer-popover",
    "--glass-fill-raised",
    "--glass-ring-raised",
    "--elevation-3",
    "--surface-1",
    "--surface-control",
    "--radius-xl",
    "--radius-lg",
    "--space-1",
    "--space-2",
    "--type-caption",
    "--text",
    "--text-muted",
    "--text-label",
    "--brand-blue",
    "--error-ink",
    "--border-rule",
    "--glass-highlight",
    "--glass-fill-active",
    "--focus-ring",
    "--focus-ring-width",
    "--duration-fast",
    "--ease-soft",
    "--ease-standard"
  ]
}

Raw file: https://design.werklist.com/agent/components/menu