# A command menu with pages · Components

<!-- https://learn-ui.com/chapters/components/command-menu -->

Maggie Appleton catalogues the pattern in [Command K Bars](https://maggieappleton.com/command-bar) (November 2022). **Command bars** (Command bars are command-line bars that pop up in the middle of the screen when you hit a certain keyboard shortcut; also known as command palettes, command launchers, or omniboxes, traditionally on CMD + K.) “are command-line bars that pop up in the middle of the screen when you hit a certain keyboard shortcut,” traditionally CMD + K, with CMD + E and CMD + / as contenders. Her examples are Linear, Todoist, Framer, Tana, Raycast, and Lazy; the lineage runs to Apple’s Spotlight in MacOS 10.4 Tiger (2005, CMD + Space) and Quicksilver.

### Why a bar beats a menu

GUIs make affordances visible, but “they don’t scale very well to complex systems with hundreds of commands”; Cinema 4D is her counter-example. With a bar, “rather than remembering which sub-sub-sub menu a function lives in, users need only remember its name,” and fuzzy search means not even that. Rare items stashed in the bar clear screen space; commandbar.com, kbar, and cmdk are ready-made.

### cmdk and what it costs

Paco Coursey’s **cmdk** (⌘K is a command menu React component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically.) [README](https://github.com/pacocoursey/cmdk) says: “⌘K is a command menu React component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically.” Written in 2019, used by Rauno Freiberg for the Vercel command menu in 2020, rewritten in 2022 with help from Shu. On [Devouring Details](https://devouringdetails.com) Rauno calls it “downloaded millions of times per week.”

> Figure. TSXPaco Coursey, cmdk README

Each part forwards props and ref and carries a cmdk- data attribute for styling; Dialog composes Radix’s Dialog. Items infer value from textContent; you can pass a filter, keywords, shouldFilter false, and loop. The FAQ: accessible, yes, tested with VoiceOver; virtualization, no, but good to 2,000 to 3,000 items; listen for ⌘K, no, “do it yourself to have full control over keybind context.”

The [ARCHITECTURE document](https://github.com/pacocoursey/cmdk/blob/main/ARCHITECTURE.md) explains the cost. The library “is born from a simple constraint: can you write a combobox with filtering and sorting using the compound component approach?” For a combobox it is “a terrible, terrible constraint that we’ve spent 2 years fighting.” Every item stays in the React tree and adds or removes itself from the DOM; “the DOM is authoritative,” so selection order follows render order.

He rejected React.Children (cannot peek inside composed components), object arrays (their interface grows with edge cases), and render props (inelegant). Selection moved from index to value because Strict Mode runs effects twice. The price: 2,000 items filtered to 2 still allocate 2,000 Item instances, though the DOM shrinks to 2. His [original Command Menu](https://paco.me/craft/command) (2021) tested 249 items, then aimed at 2,000.

Source

The constraint, the DOM-is-authoritative rule, and the rejected alternatives are from cmdk’s ARCHITECTURE.md, which opens by warning that it is a work in progress.

### Depth through pages

The README’s example: “selecting ‘Change theme…’ should show new items ‘Dark theme’ and ‘Light theme’. We call these sets of items ‘pages’, and they can be implemented with simple state,” with Escape or Backspace on an empty search popping out. Maggie sees the same move in Tana.

Rauno’s [craft index](https://rauno.me/craft) has Command Menu (November 2021) and ⌘K Breadcrumbs (December 2022), the trail that says which page you are on.

> Figure. TSXPaco Coursey, cmdk README

The figure is a command menu with two pages: items ending in an ellipsis open a page, the breadcrumb row changes, and Backspace on an empty input goes back.

> Figure 2. A command menu with pages. Type to filter, or pick an item with the arrow keys and Enter. Items ending in an ellipsis open a nested page; the breadcrumbs show where you are, and Backspace on an empty input or Escape steps back out. The list keeps a fixed height so the card never jumps between pages.Illustrative numbers

### Do not animate it

The figure does not animate its opening, by rule. In [Invisible Details of Interaction Design](https://rauno.me/craft/interaction-design) Rauno makes command menus his example of when not to animate: at “hundreds of times a day, it does start to feel more like cognitive burden after seeing the same animation for the hundredth time.” Emil Kowalski’s skill file puts the command palette toggle in the 100-plus-times-a-day row: “No animation. Ever.” See [Frequency and novelty](https://learn-ui.com/chapters/invisible-details/frequency-and-novelty).

Instead, be fast and keyboard-first: filter as you type, keep the selection stable, make Escape and Backspace the way back up a page, and put the shortcut next to the action, as Maggie notes Todoist does. cmdk refuses to decide the keybinding, the styling, and the items. Those are yours.
