{"slug":"command-palette","meta":{"title":"Command Palette","slug":"command-palette","kind":"pattern","summary":"One keyboard-summoned box that searches records and actions together, so an expert reaches anything in the product without navigating to it.","problem":"Someone who uses the product all day knows exactly what they want and still has to travel — click a section, filter a list, find a row, open a menu. The navigation was built for people learning the app, and they stopped learning it months ago.","family":["find","act"],"data_shape":["app","collection"],"principles":["friction","surface-dont-bury"],"interaction":["navigation","search"],"density":"low","complexity":"medium","status":"stable","visibility":"public","use_when":["People use the product daily and know what they want before they look for it.","There are more destinations and actions than a navigation bar can honestly hold.","Records have names people remember and would type."],"avoid_when":["The product is used occasionally. A palette rewards memory nobody has built.","It would become the only route to something. A palette is an accelerator, never the sole path.","The app has six screens, where navigation is already faster than typing."],"alternatives":[{"slug":"persistent-navigation","when":"People are still learning the product and need to see what exists."},{"slug":"global-search","when":"People want to find records, not run actions, and expect a results page."}],"ask_leo":"Add a command palette to this app.\n\n- Open it with Cmd+K and Ctrl+K from anywhere, and give it a visible entry\n  point too — a search affordance in the header showing the shortcut — so\n  people who never learn the key can still find it.\n- Search records AND actions in one list, grouped with headings, so someone\n  who types \"invoice\" sees both matching invoices and \"Create invoice\".\n- Rank by what the person used recently, then by match quality. Show something\n  useful when the box is empty: recent records and the most common actions.\n- The whole thing works from the keyboard: arrows to move, Enter to run, Escape\n  to close, and focus returns to where it was.\n- Show the matched text in each result so it is obvious why a row is there.\n- Never make the palette the only way to reach something. It is an accelerator\n  on top of real navigation, not a replacement for it.\n","related":[{"title":"Cmd+K Global Search","url":"/cookbook/global-search-command-palette","summary":"The implementation — the Rails and Stimulus version of this pattern."},{"title":"Surface, don't bury","url":"/patterns/surface-dont-bury","summary":"Why a palette does not excuse a badly ranked navigation bar."}]},"body":"## Anatomy\n\n```\n┌──────────────────────────────────────────────────┐\n│ ⌘K  invoi|                                       │\n├──────────────────────────────────────────────────┤\n│ ACTIONS                                          │\n│   ⌁ Create invoice                               │\n│   ⌁ Export invoices as CSV                       │\n│ INVOICES                                         │\n│ ▸ INV-1041  Riverside Fit-Out      overdue       │\n│   INV-1043  Kestrel Joinery        overdue       │\n├──────────────────────────────────────────────────┤\n│ ↑↓ move   ↵ open   esc close                     │\n└──────────────────────────────────────────────────┘\n```\n\nFour things separate a palette from a search box:\n\n1. **Actions and records in one list.** \"Invoice\" is both a noun and a job. A\n   palette that only finds nouns sends people back to a menu for the verb.\n2. **A useful empty state.** Before typing, show recents and common actions.\n   This is what teaches people the palette is worth opening.\n3. **Complete keyboard control**, including returning focus on close.\n4. **A visible entry point.** The shortcut is for people who know it; the\n   affordance in the header is how anyone becomes one of those people.\n\n## Why it works\n\nIt decouples reach from structure. Navigation depth is a compromise between\nwhat is frequent and what exists; a palette makes that compromise irrelevant for\nanyone willing to type, because everything is one keystroke away regardless of\nwhere it lives.\n\nThat is why it is filed under both [find](/patterns/families/find) and act. Its\nreal subject is not searching — it is collapsing \"get to the thing\" and \"do the\nthing\" into a single gesture.\n\n## The failure it invites\n\n**A palette is not a fix for bad navigation.** It is easy to add one and stop\nranking the nav bar, because the people who complain loudest are the experts and\nthey now have their accelerator. Everyone else — new hires, occasional users,\nanyone in their first month — is left with the structure you gave up on.\n\nWatch for the palette becoming the only route to a feature. That is the point at\nwhich it stopped being an accelerator and became a hiding place.\n\n## Getting it wrong\n\n- **Results with no explanation.** If it is not obvious why a row matched,\n  people stop trusting the ranking and go back to the menu.\n- **Ranking by relevance only**, ignoring recency. What someone touched an hour\n  ago is almost always what they want now.\n- **No visible entry point**, so only people told about it ever use it.\n- **Trapping focus on close**, which is a small thing that makes the whole\n  feature feel unfinished.\n\n## Exemplars\n\n**Linear** is the reference implementation: records, actions, navigation and\nsettings in one ranked list, and the product is genuinely faster to drive from\nthe palette than from its own sidebar.\n\n**VS Code** shows the ceiling and the risk in the same product. Its palette\nexposes every command, which makes it enormously powerful and also means many\nfeatures have no discoverable home outside it.\n\n**Slack** demonstrates the ranking point: the empty state is recent\nconversations, which is right almost every time, so opening the palette is\nusually already the answer.\n\nThe extractable rule: **a palette rewards memory, so it must be built on\nrecency.** Match quality alone treats every session as the first one.\n"}