StartFoundationsComponentsContent

Menu

A menu is a list of actions that opens from a button. Choosing an item runs a command; nothing is saved as a value. It is also called a dropdown, action, or overflow menu.

Stable Figma
OverviewUsageAPIAccessibility
Rename Duplicate Archive
<tk-menu>
  <tk-tooltip slot="trigger" type="label">
    <tk-icon-button label="Row actions"><tk-icon name="more-horizontal"></tk-icon></tk-icon-button>
  </tk-tooltip>
  <tk-menu-item>Rename</tk-menu-item>
  <tk-menu-item>Duplicate</tk-menu-item>
  <tk-menu-item>Archive</tk-menu-item>
</tk-menu>

Anatomy

Part What it is
trigger your button in the trigger slot; it gets the menu ARIA
panel the list; 160–288px wide, sized to its content
item tk-menu-item: one row, at least 32px tall
check the ✓ for checked items; when any item can be checked, every row keeps room for it
icon an optional 16px icon in the icon slot
description an optional second line
trailing an optional hint or badge in the trailing slot
divider tk-divider or <hr>: a line between groups
group tk-menu-group: a titled section
submenu a nested tk-menu, opened from a parent row

Items

View Show grid Snap to grid Name Date modified
<tk-menu>
  <tk-button slot="trigger">View<tk-icon slot="icon-end" name="chevron-down"></tk-icon></tk-button>
  <tk-menu-item type="checkbox" checked>Show grid</tk-menu-item>
  <tk-menu-item type="checkbox">Snap to grid</tk-menu-item>
  <tk-divider></tk-divider>
  <tk-menu-group label="Sort by">
    <tk-menu-item type="radio" checked>Name</tk-menu-item>
    <tk-menu-item type="radio">Date modified</tk-menu-item>
  </tk-menu-group>
</tk-menu>
  • command (default): runs an action and closes the menu.
  • checkbox: turns a view option on or off, such as showing a grid. The menu stays open, so people can change several.
  • radio: picks one option from its tk-menu-group and closes the menu. Put radios in a titled group.
  • Checked items change how people see the screen (sort order, visible columns, density), and the change applies at once. They never hold a form value; that's a Select.
  • preventDefault() on an item's click stops both the check change and the close, for example to ask first. Setting checked from code fires nothing.

Danger

Project Rename Duplicate Delete project…
<tk-menu>
  <tk-button slot="trigger">Project</tk-button>
  <tk-menu-item>Rename</tk-menu-item>
  <tk-menu-item>Duplicate</tk-menu-item>
  <tk-divider></tk-divider>
  <tk-menu-item danger>Delete project…</tk-menu-item>
</tk-menu>
  • danger marks an action that loses data. It works on command items only.
  • Put it last, after a divider.
  • Always confirm it with a confirm dialog; end the label with "…" to show that a step follows.
  • Red means data loss, not leaving: "Leave team" isn't red. Name the action in the label.

Icons, descriptions, and hints

Edit Copy⌘C Copy link Move to trash
<tk-menu>
  <tk-button slot="trigger">Edit</tk-button>
  <tk-menu-item><tk-icon slot="icon" name="copy"></tk-icon>Copy<span slot="trailing">⌘C</span></tk-menu-item>
  <tk-menu-item description="Everyone with the link can view"><tk-icon slot="icon" name="link"></tk-icon>Copy link</tk-menu-item>
  <tk-menu-item disabled><tk-icon slot="icon" name="trash"></tk-icon>Move to trash</tk-menu-item>
</tk-menu>
  • Icons: give every item an icon or none. The menu sizes and colors them.
  • Descriptions: keep them rare and short; most menus are one line per item.
  • Trailing: a shortcut hint or a badge, shown as text. It doesn't set up the shortcut; wire the key yourself. Screen readers read it after the label, so keep it short. Nothing interactive here.

States

Hover and keyboard focus look the same: a light tint on the row. Pointing at an item moves focus to it.

  • disabled: the item stays in the menu and can still be reached with the arrow keys, but does nothing. People can see the command exists. If every item is unavailable for the same reason, disable the trigger instead.
  • Hide items people will never be allowed to use, such as admin-only actions.
  • checked: shows the ✓ on checkbox and radio items.

Opening and closing

Opening moves focus to the first item (the last with ↑).

Close path Focus goes to
Esc the trigger; a dialog around the menu stays open
choosing a command or radio item the trigger, unless the action moves focus, such as opening a dialog
choosing a checkbox item the menu stays open
Tab / Shift+Tab the next or previous element; nothing runs
click outside where the click landed
clicking the trigger again the trigger
  • The menu opens below the trigger and moves above near the bottom of the screen. It follows the trigger on scroll and is never clipped by its container.
  • Long labels are cut with an ellipsis. Menus don't scroll; keep them to about 12 items.

Triggers

  • A tk-button with a label and a chevron-down icon for page actions. Don't repeat its word in the items: "Export" opens "PDF" and "CSV", not "Export PDF".
  • A more-horizontal tk-icon-button in a type="label" Tooltip for overflow actions, such as on a table row. Name the scope: "Row actions", "More actions".

Context menus

Quarterly report.pdf
Open Rename Download
<tk-menu trigger="context" label="File actions">
  <div slot="trigger">Quarterly report.pdf</div>
  <tk-menu-item>Open</tk-menu-item>
  <tk-menu-item>Rename</tk-menu-item>
  <tk-menu-item>Download</tk-menu-item>
</tk-menu>

With trigger="context", the trigger slot holds the area people right-click. The menu is otherwise the same. It opens three ways:

  • Right-click in the area: the menu opens at the pointer.
  • Long press on touch, for 500ms; moving or scrolling cancels it.
  • Shift+F10 or the ContextMenu key while focus is in the area. The menu makes the area focusable if it isn't.

Rules for context menus:

  • Name the menu with label, or aria-label on the area. The area's text is never used as the name.
  • Every command must also be reachable from the main screen. People can't discover a right-click, and touch and keyboard users may never find it.
  • Hide items that don't apply here, instead of disabling them.
  • No shortcut hints.
  • Put the most likely commands first, nearest the pointer.

The browser's own context menu stays available everywhere outside the area.

Actions Rename Share Email Copy link
<tk-menu>
  <tk-button slot="trigger">Actions</tk-button>
  <tk-menu-item>Rename</tk-menu-item>
  <tk-menu>
    <tk-menu-item slot="trigger">Share</tk-menu-item>
    <tk-menu-item>Email</tk-menu-item>
    <tk-menu-item>Copy link</tk-menu-item>
  </tk-menu>
</tk-menu>

A submenu is a tk-menu inside a menu, with a tk-menu-item as its trigger: the parent row. The row gets its chevron and ARIA, and the submenu takes its name from the row.

  • Hover, click, Enter, Space, or → open it. A parent row only opens its submenu; it never runs a command.
  • Moving diagonally from the row into the open submenu doesn't close it.
  • ← or Esc close the submenu and return focus to its row.
  • Choosing an item closes every level and returns focus to the trigger.
  • It opens on the side with room. A disabled parent row never opens.
  • Radio sets and the ✓ column are per level.

Use submenus sparingly:

  • One level only, with at most about 5 items.
  • Not to pick a value, and not just to tidy up; use a group title instead.
  • If people open the menu to reach the submenu, make the submenu the menu.
  • Avoid them on touch-first screens.