Every action in your product, one keystroke away.
A typed, accessible command palette for React applications, with grouped actions, nested pages and fuzzy search built in. Full source included.
Register actions. It handles the rest.
Search, keyboard navigation, focus and list virtualization live inside the component, so it behaves the same in every product it ships in.
The source lives in your project, not behind a package. Extend it, restyle it through tokens and ship it in your own product without waiting on anyone.
- Runs on
- React 19 or later. Works with Vite, Next.js and Remix.
- Requires
- None beyond React 19. The component includes its own search and virtualization.
What you do not have to build. Your product is what is left.
Typed action registry
Actions, groups and pages are declared with full TypeScript inference, so a missing handler is a compile error.
Nested pages
Drill from a command into a sub-list and back with the keyboard, with the breadcrumb and focus handled for you.
Fuzzy search
Ranks matches by label, keywords and group, and highlights the matched characters in the result.
Accessible by default
Combobox semantics, a live result count and full keyboard operation, with focus returned to where it started on close.
Async sources
Load results from an API as the query changes, with loading and empty states built in and stale requests ignored.
Token-driven styling
Color, radius and spacing come from CSS variables, so a restyle is a variable change, not a source edit.
Drops into your project. Stays intact when you edit.
- Integration
- Register actions once and the menu handles search, keyboard navigation and focus. Mount it at the root of your app and bind it to a shortcut.
- Install
- Copy the CommandMenu folder into your project, mount the component once near the root, then pass your actions through the actions prop. The documentation walks through each step.
- Customizable
- Actions, groups, pages, placeholder text, the open shortcut, filtering, loading and empty states, and every design token are exposed through props and CSS variables.
- Protected
- Keyboard handling, focus management, ranking and list virtualization stay inside the component, so they behave the same in every project.
Exactly what you can configure. Each one with its type and default.
- actionsCommandAction[]Default []
The commands the menu can run. Each has an id, a label, optional keywords, a group and a handler.
- openbooleanDefault undefined
Controls the open state from outside. Leave unset to let the menu manage itself.
- onOpenChange(open: boolean) => voidDefault undefined
Called whenever the menu opens or closes.
- shortcutstringDefault Mod+K
The key combination that toggles the menu. Mod resolves to Command on macOS and Control elsewhere.
- placeholderstringDefault Search commands
Placeholder text for the search field.
- filter(query: string, action: CommandAction) => numberDefault fuzzyScore
Replaces the ranking function. Return 0 to hide an action.
- loadingbooleanDefault false
Shows the loading state while an async source resolves.
- emptyStateReactNodeDefault No results
Rendered when no action matches the query.
The last questions, answered plainly.
Any React 19 project. It is a plain component with no framework-specific imports, so Vite, Next.js and Remix all work.
No. It has no runtime dependency beyond React. Search and virtualization are part of the source you receive.
Yes. Color, radius, spacing and type are CSS variables. You can also replace any part of the markup through the slots prop.
Yes. It follows the combobox pattern, announces the result count, traps focus while open and returns it on close. Known limitations are listed in the documentation.
Personal Use covers products you own. Commercial Use covers products you build for clients. Neither allows reselling the source.
Messages go straight to the studio that made the component. There is no support queue.