Command & Control Patterns (Menus, Toolbars, Command Palette)
Master menus, toolbars, and command palettes — the three command surfaces that define how expert users discover, trigger, and repeat actions in complex software.
11 min read
The full lesson
Every time a user triggers an action that is not visible on screen, they use a command surface — a menu, a toolbar button, or a command palette. Getting these right determines whether power users can work at full speed, whether keyboard-only users can navigate without friction, and whether new users can discover features without reading a manual. Get them wrong, and you end up with buried actions, unrecognizable icons, and support tickets asking “how do I do X?”
This lesson covers the three major command patterns, when each is appropriate, how they work together, and what accessibility and keyboard requirements turn a functional implementation into a genuinely usable one.
The Three Command Surfaces and Their Jobs
Command patterns run on a spectrum from high discoverability (menus) to high efficiency (command palettes). Each one serves a different user intent.
Menus organize commands into a hierarchy that users browse. They trade speed for discovery. A user who does not know a feature exists can find it by reading through the menu. The cost is extra steps: every level of nesting is a click and a small cognitive tax.
Toolbars show the most-used commands as persistent, always-visible controls. They trade coverage for speed. A well-designed toolbar puts the 20% of commands that cover 80% of use cases one click away. The failure mode is toolbar bloat: when everything is “important,” nothing stands out.
Command palettes (also called command bars or quick-open panels) are a single keyboard-triggered modal where users type to find and run any command. They were popularized by code editors (Sublime Text, then VS Code) and spread to design tools (Figma), productivity apps (Linear, Notion, Raycast), and enterprise software. They excel for expert users who know what they want but can’t remember where it lives.
These three surfaces are not competing options — they are layers. A mature command architecture exposes every action in the menu (for discovery), promotes frequent actions to the toolbar (for speed), and makes everything keyboard-accessible via the command palette (for power users).
Menus: Structure, Depth, and the Hamburger Trap
Organizing a Menu Hierarchy
Menu design is taxonomy design. The goal is a structure that matches how users think about commands — not how the engineering team organized the codebase.
Effective menu organization follows these principles:
- Group by task, not by implementation. “Export,” “Share,” and “Publish” are related from a user’s perspective even if they touch different backend services. Group them under a “Share & Export” parent.
- Keep the hierarchy shallow. Two levels is the practical maximum for desktop menus. Three levels is acceptable only in complex creative tools like DAWs or 3D modelers. Every extra level takes longer to navigate and increases the chance a user gives up and searches instead.
- Put the most-used items first within each group. Users scan menus top to bottom. Burying “New File” below six rarely-used options adds friction for the most common action.
- Use separator lines sparingly and consistently. A separator marks a conceptual boundary. If every item has a separator, they all lose meaning.
Keyboard Shortcuts and Accelerators
Every menu item should show a keyboard shortcut next to its name. This is how users learn shortcuts: they see the shortcut next to the action they just triggered with a mouse, and over time they internalize it and stop reaching for the menu. Hiding shortcuts to “reduce visual noise” breaks this learning loop.
The Desktop Hamburger Anti-Pattern
The hamburger menu — a three-line icon that hides navigation behind a tap — was a reasonable choice on 320px mobile screens in 2012. On desktop it is a persistent usability problem. Research consistently shows hamburger menus on desktop produce roughly 39% slower task completion and about half the feature discoverability compared to persistent navigation.
Context Menus
Right-click (or long-press) context menus surface actions relevant to a specific element. They are powerful precisely because they adapt to what is selected. Follow these rules:
- Include only actions that apply to the current selection. An empty or irrelevant context menu erodes trust faster than having no context menu at all.
- Mirror items that exist in the main menu. Context menus are shortcuts to relevant main-menu actions, not a separate command namespace.
- Never make an action available only in a context menu. Users who don’t know about right-clicking will never find it.
Toolbars: Curation, Overflow, and Icon Clarity
What Goes in a Toolbar
A toolbar is a curated shortcut list, not a complete command index. For every candidate item, ask: “Would most users in this context benefit from having this one click away?” If the honest answer is “some power users, sometimes,” it belongs in a menu or command palette — not the toolbar.
| Toolbar candidates | Belongs elsewhere |
|---|---|
| New, Save, Undo/Redo | Preferences and settings |
| Bold, Italic, Link (in text editors) | Advanced format options |
| Play, Pause, Stop (in media tools) | Export format configuration |
| Zoom in, Zoom out, Fit to screen | Debug / developer actions |
Icon Clarity and Labels
Icon-only toolbars are a chronic source of confusion outside of a few well-established conventions (the floppy disk for save, the scissors for cut). Best practice:
- Show visible text labels on toolbars whenever space allows. Text plus icon is more scannable and learnable than icon alone.
- When space forces icon-only display, show a tooltip on hover within 300ms. This is the primary fallback for discoverability.
- Include the keyboard shortcut in the tooltip: “Bold (Cmd+B)” rather than just “Bold.” This also teaches the shortcut passively.
- Avoid abstract icons for domain-specific actions. When in doubt, label it.
Toolbar Overflow
When a toolbar runs out of horizontal space, items should not simply disappear. Collect them into an overflow menu — typically a ”…” or chevron button at the end of the toolbar. This is better than wrapping to a second row, which destabilizes the layout for surrounding content.
Do
- Curate the toolbar to the 6–10 actions that cover the vast majority of use cases for the current context.
- Show text labels alongside icons wherever space allows; fall back to icon-only with descriptive tooltips at narrow widths.
- Collect overflow items into a clearly labeled menu rather than hiding or wrapping them.
- Let users customize which actions appear in the toolbar when the product has a large or domain-specific command set.
- Include keyboard shortcuts in tooltips so the toolbar teaches expert behaviors passively.
Don't
- Add every available action to the toolbar in the name of “making things accessible” — a toolbar with 25 items is harder to use than one with 8.
- Use icon-only buttons for non-standard actions without a tooltip fallback — users will not guess what an abstract icon means.
- Remove the toolbar entirely at narrow viewports without providing an equivalent command surface (overflow menu or command palette).
- Refresh toolbar contents on every state change without a stable anchor — shifting buttons cause mis-clicks.
Contextual Toolbars
Many modern editors — Notion, Google Docs, Figma — use floating contextual toolbars that appear near a selection. Think of rich-text formatting controls that float above selected text, or shape alignment options that appear when a layer is selected. These reduce how far the cursor must travel and surface only relevant commands.
One key constraint: the floating toolbar must not cover the content it is acting on. Positioning logic needs to detect when the default position would overlap the selection and flip to the opposite side.
Command Palettes: The Power-User Interface
Why Command Palettes Won
Command palettes solve a real problem with deep software: the more powerful the tool, the more commands it has, and the harder it becomes to remember where anything lives. A command palette collapses the entire command space into one searchable, keyboard-triggered interface. The user does not need to know where a command lives — they just need to know roughly what it is called.
VS Code’s command palette (Cmd+Shift+P) is the archetype. Figma’s Quick Actions (Cmd+/) brought it to design tools. Linear, Raycast, Superhuman, and Vercel’s dashboard have all made the command palette a first-class navigation surface.
What to Index in a Command Palette
A command palette is only as useful as what it can find. Index:
- Every action available in any menu or toolbar
- Navigation targets (pages, documents, projects, settings screens)
- Recent files and frequently-used items (surfaces them without typing)
- Dynamic results: search within content (for tools that hold content like Notion or Linear)
- Settings toggles (for example, “Toggle dark mode” or “Show grid”)
Do not index actions with dangerous, irreversible consequences without a confirmation step. Triggering “Delete project” from a command palette with a single Enter keypress is error-prone. Add a confirmation step, or leave that command out of the palette entirely.
Fuzzy Matching and Ranking
Strict prefix matching is not enough for a command palette. Users type abbreviations, mid-string fragments, and misspellings. Implement fuzzy matching that:
- Matches any substring, not just the start of a word
- Supports acronym matching (so “tdo” matches “Toggle Dark Mode”)
- Weights recently used commands higher than rarely used ones
- Surfaces the globally most-used commands when the input is empty
Keyboard Navigation Requirements
A command palette that requires mouse interaction defeats its own purpose. Full keyboard operation is a functional requirement:
- Arrow keys navigate results
- Enter executes the focused result
- Escape closes the palette and returns focus to whatever had it before
- Tab can move focus to a secondary action (for example, a settings link within a result row)
Keyboard Navigation and WCAG 2.2 Requirements
Focus Management
Every command surface — menus, toolbars, command palettes — must maintain a logical, predictable focus order. The most relevant WCAG 2.2 success criteria:
- 2.1.1 Keyboard (Level A): All functionality must work by keyboard alone. For toolbars, this means arrow-key navigation between toolbar items within the toolbar’s focus context — not just Tab stops between every button.
- 2.4.11 Focus Not Obscured (Level AA, new in WCAG 2.2): When a component receives focus, it must not be entirely hidden by sticky headers, persistent toolbars, or overlaid panels. If your toolbar is sticky at the top, make sure focused elements near the top of the viewport are not covered by it.
- 2.4.12 Focus Not Obscured (Enhanced) (Level AAA): The focused component is not even partially hidden.
- 2.5.8 Target Size Minimum (Level AA, new in WCAG 2.2): Interactive targets must be at least 24x24 CSS pixels (with exceptions for inline targets and targets with adequate spacing). Desktop toolbar buttons usually clear this easily; mobile toolbar buttons need explicit minimum tap target sizing.
Toolbar ARIA Patterns
Toolbars should use the WAI-ARIA toolbar role with an aria-label that identifies the toolbar’s purpose. Navigation within a toolbar follows the “roving tabindex” or aria-activedescendant pattern — only one toolbar item sits in the Tab sequence at a time, and arrow keys move between items within the toolbar. This prevents the Tab key from creating dozens of consecutive stops through a long toolbar.
<div role="toolbar" aria-label="Text formatting">
<button type="button" aria-pressed="false">Bold</button>
<button type="button" aria-pressed="false">Italic</button>
<button type="button" aria-pressed="false">Underline</button>
<separator role="separator" />
<button type="button">Link</button>
</div>
For menus, use the menu and menuitem ARIA roles. Submenus use menuitem with aria-haspopup="true" and aria-expanded reflecting open state. Arrow keys navigate, Enter or Space activates, and Escape closes and returns focus.
For the command palette dialog, use role="dialog" with aria-modal="true" and the inert attribute on background content when the palette is open. The inert attribute is now well-supported across browsers as of 2024, and it is the modern replacement for manual tabindex manipulation when trapping focus.
Keyboard Shortcut Conflicts
Custom keyboard shortcuts must not override browser or OS reserved shortcuts. Cmd+C, Cmd+V, Cmd+Z, F5, and similar bindings must remain available. Before shipping a new shortcut scheme, audit it against the platform’s reserved key list. A keyboard shortcut customization UI is the gold standard for power-user tools, but even a static, well-chosen set of shortcuts beats having none at all.
Responsive and Cross-Context Adaptation
Command surfaces behave differently across contexts and must adapt thoughtfully — not simply disappear on small screens.
Desktop: Full menu bar or menu button, persistent toolbar with text-plus-icon labels, command palette on Cmd+K or equivalent.
Tablet (pointer + touch): Simplify the toolbar — keep the most essential items and move secondary commands to an overflow menu. Use long-press for context menus. Keep the command palette available.
Mobile: Traditional menu bars disappear at mobile widths. Replace with a bottom navigation bar for primary navigation, plus a floating action button or bottom sheet for context-sensitive commands. Toolbars compress into icon-only strips; replace hover tooltips with labels shown on first use. The command palette is less common on mobile, but it works well in productivity apps. Notion’s slash commands are a mobile-adapted variant of the pattern.
The outdated approach is to hide the entire command surface at narrow widths and hope users discover commands by trial and error. The modern approach uses container queries to adapt each command component independently at its own breakpoint, rather than snapping everything at once with a single device-width media query.
Common Failure Modes and How to Fix Them
| Failure | Symptom | Fix |
|---|---|---|
| Action buried too deep | Users search help to find a command they use weekly | Promote to toolbar or surface in command palette; flatten menu hierarchy |
| Icon-only toolbar | Support tickets asking what icons do | Add text labels or ensure every icon has a tooltip with the action name and keyboard shortcut |
| No keyboard path to a command | Keyboard-only users are blocked | Ensure every action is accessible via menu or command palette; audit with keyboard-only navigation |
| Context menu as the only path | Features hidden from users who do not right-click | Mirror every context menu item in a main menu or toolbar |
| Command palette with weak search | Users type the exact command name and get no results | Implement fuzzy matching with acronym support and recently-used weighting |
| Toolbar reflows on state change | Buttons shift position, causing mis-clicks | Lock toolbar layout; use overflow menu for items that do not fit |
| Focus not returning after closing a menu | Users lose their place in the keyboard flow | On close, return focus to the element that triggered the menu |