What is Command palette?
Command palette: A command palette is a searchable modal, usually opened with Cmd+K or Ctrl+K, that lets users run actions and jump to pages by typing.
A command palette is a keyboard-first launcher inside an app. The user presses a shortcut, a dialog opens with a search field, and typing filters a list of commands: navigate to a page, create a record, toggle a setting, switch workspace. Editors such as VS Code and Sublime Text popularized it, and most developer tools and SaaS dashboards now include one. It gives power users one place to reach any feature without learning where every button lives.
Anatomy
- A modal container positioned near the top of the viewport, so results can grow downward.
- A search input focused on open, with placeholder text that hints at what can be searched.
- Grouped results: recent items first, then navigation, actions and settings, each with an optional icon and keyboard shortcut hint.
- An empty state when nothing matches, ideally with a suggestion.
- A footer listing the keys that work: arrows to move, Enter to run, Escape to close.
Accessibility
A command palette is a modal dialog that contains a combobox. The dialog needs an accessible name, even if the title is visually hidden, and must trap focus while open. On open, focus goes to the input. Arrow keys move the highlighted command by updating aria-activedescendant on the input, Enter runs it, and Escape closes the palette and returns focus to whatever was focused before. The results list uses role="listbox" with role="option" items, and group headings should be labeled so screen reader users hear the section as they move.
How to build one in React
Listen for the shortcut once at the app shell and control the palette's open state from there. Call preventDefault so browsers that bind Ctrl+K to the address bar do not steal it while your app has focus.
"use client"
import * as React from "react"
import { useRouter } from "next/navigation"
import { CommandPalette } from "@/components/ui/command-palette"
export function AppCommands() {
const [open, setOpen] = React.useState(false)
const router = useRouter()
React.useEffect(() => {
function onKey(e: KeyboardEvent) {
if (e.key.toLowerCase() === "k" && (e.metaKey || e.ctrlKey)) {
e.preventDefault()
setOpen((o) => !o)
}
}
window.addEventListener("keydown", onKey)
return () => window.removeEventListener("keydown", onKey)
}, [])
return (
<CommandPalette
open={open}
onOpenChange={setOpen}
commands={[
{ id: "new", label: "New project", onSelect: () => router.push("/projects/new") },
{ id: "billing", label: "Open billing", onSelect: () => router.push("/settings/billing") },
]}
/>
)
}
Common mistakes
- Making it the only way in. Every command should also exist somewhere in the visible UI. The palette is a shortcut, not a hiding place.
- Exact substring matching only. Match on synonyms and keywords too, so "invoice" finds Billing.
- No way to discover it. Show the shortcut in the search field of the top bar, and list it in a shortcut cheat sheet.
MiniDev ships CommandPalette and CommandDialog in the navigation category.
Command PaletteuiCmd K style command palette in a dialog with a search field that filters commands as you type, runs the chosen action and closes. Shows an empty state.npx shadcn@latest add ui.minidev.pro/r/command-palette.jsonCommand DialoguiCommand dialog that opens the command palette in a modal from a list of commands with labels and handlers. Wire it to a Cmd K shortcut in your React app.npx shadcn@latest add ui.minidev.pro/r/command-dialog.json