Menu keyboard shortcuts

How to show keyboard shortcuts alongside menu actions so people can discover and learn them.


A menu is where most people find out a shortcut exists. When an action in a DropdownMenu also has a keyboard shortcut, show the shortcut on the action — it teaches the shortcut in passing, without a separate reference to go looking for.

Put the shortcut in the item's elementAfter slot, using KeyboardShortcut. The slot is pinned to the trailing edge of the menu, so shortcuts line up down the whole menu no matter how long each label is, and menus across different surfaces end up spaced the same way.

Loading editor

Alignment

Let elementAfter do the alignment. It reserves the trailing edge and applies the gap, so every item in the menu agrees without any per-item measuring.

Do
<DropdownMenuItem icon="zoom-in" onClick={zoomIn} elementAfter={<KeyboardShortcut hotkey="Mod+=" />}>
  Zoom in
</DropdownMenuItem>
Don't
<DropdownMenuItem icon="zoom-in" onClick={zoomIn}>
  <InlineStack alignInline="space-between" alignBlock="center" w="full" gap="200">
    <span>Zoom in</span>
    <KeyboardShortcut hotkey="Mod+=" />
  </InlineStack>
</DropdownMenuItem>

Wrapping the label yourself puts the shortcut inside the label rather than in the item's trailing slot. Each call site then picks its own gap, the spacing drifts between menus, and the shortcut no longer aligns with a trailingIcon on a neighboring item.


Content

  • Only show shortcuts that are actually bound. A shortcut in a menu is a promise that pressing those keys does the same thing. Don't show one for an action that has no handler registered.
  • Use Mod for the platform modifier. KeyboardShortcut renders it as ⌘ on macOS and Ctrl elsewhere, so a single hotkey covers both.
  • Leave the slot empty when there's no shortcut. Actions without one simply omit elementAfter — the remaining shortcuts still line up. Never add a placeholder to fill the gap.
  • Don't repeat the shortcut in the label. "Zoom in (⌘=)" duplicates what the slot already shows.

Behavior

  • The shortcut is a label, not a control. It isn't focusable and isn't a separate click target; activating any part of the item runs the action.
  • Keep the menu open for repeatable actions. Zooming in is something people do several times in a row, so those items set shouldCloseOnClick={false}. One-shot actions should close as usual.
  • Shortcuts keep working while the menu is closed. The menu documents them; it doesn't own them. Register the handler where the action lives.

Beyond menus

elementBefore and elementAfter are the same pair of slots on NavItem, Select options and the select trigger, Button, Link and TextField. Reach for them whenever something needs to sit at the leading or trailing edge of a component, rather than composing it into the label.

On this page