What is cmdk?
cmdk is a React component library for building command menus. It provides a flexible and customizable way to create command palettes, similar to those found in applications like VSCode, Figma, and Notion.
What are cmdk's main functionalities?
Basic Command Menu
This code demonstrates how to create a basic command menu using cmdk. It includes an input field for typing commands and a list of command items.
import { Command } from 'cmdk';
function App() {
return (
<Command>
<Command.Input placeholder="Type a command or search..." />
<Command.List>
<Command.Item>First Command</Command.Item>
<Command.Item>Second Command</Command.Item>
</Command.List>
</Command>
);
}
Nested Command Menus
This code demonstrates how to create nested command menus using cmdk. It shows how to include a sub-menu within a command item.
import { Command } from 'cmdk';
function App() {
return (
<Command>
<Command.Input placeholder="Type a command or search..." />
<Command.List>
<Command.Item>First Command</Command.Item>
<Command.Item>Second Command</Command.Item>
<Command.Item>
Nested Menu
<Command.List>
<Command.Item>Nested Command 1</Command.Item>
<Command.Item>Nested Command 2</Command.Item>
</Command.List>
</Command.Item>
</Command.List>
</Command>
);
}
Custom Styling
This code demonstrates how to apply custom styling to the command menu and its elements using CSS classes.
import { Command } from 'cmdk';
import './App.css';
function App() {
return (
<Command className="custom-command">
<Command.Input className="custom-input" placeholder="Type a command or search..." />
<Command.List className="custom-list">
<Command.Item className="custom-item">First Command</Command.Item>
<Command.Item className="custom-item">Second Command</Command.Item>
</Command.List>
</Command>
);
}
Other packages similar to cmdk
react-aria
react-aria is a library that provides accessible UI primitives for React applications. It includes hooks and components for building accessible command menus, among other UI elements. Compared to cmdk, react-aria offers a broader range of accessibility-focused components but may require more setup for command menus.
downshift
downshift is a library for building flexible, enhanced input components in React. It can be used to create command menus, dropdowns, and other input-related components. While downshift provides more flexibility and control, it may require more boilerplate code compared to cmdk.
react-select
react-select is a flexible and customizable select input control for React. It can be adapted to create command menus with search functionality. However, react-select is primarily designed for select inputs and may not offer the same level of command menu-specific features as cmdk.
⌘K
Composable command palette React component. You provide the items and it filters and sorts the results for you.
$ yarn add cmdk
Usage:
import { Command } from 'cmdk'
return (
<Command.Dialog open={open} onOpenChange={setOpen}>
<Command.Input />
<Command.List>
{loading && <Command.Loading>Hang on…</Command.Loading>}
<Command.Empty>No results found.</Command.Empty>
<Command.Group heading="Letters">
<Command.Item>a</Command.Item>
<Command.Item>b</Command.Item>
<Command.Separator />
<Command.Item>c</Command.Item>
</Command.Group>
<Command.Item>Ungrouped</Command.Item>
</Command.List>
</Command.Dialog>
)
To render inline, replace Command.Dialog
with just Command
. ⌘K supports a fully composable API How?, meaning you can wrap items in other components or even static JSX:
<Command.List>
<DocsItems />
<UserItems />
{settingsItems}
</Command.List>
Parts
Command [cmdk-root]
Render this to show the command menu inline, or use Dialog to render in a elevated context.
Dialog [cmdk-dialog]
[cmdk-overlay]
Props are forwarded to Command. Composes Radix UI's Dialog component. The overlay is always rendered. See the Radix Documentation for more information.
Input [cmdk-input]
All props are forwarded to the underlying input
element.
List [cmdk-list]
Animate height using the --cmdk-list-height
CSS variable.
Item [cmdk-item]
[aria-disabled?]
[aria-selected?]
Item that becomes active on pointer enter.
Group [cmdk-group]
Groups items together with the given heading
([cmdk-group-heading]
).
Separator [cmdk-separator]
Visible when the search query is empty or alwaysRender
is true, hidden otherwise.
Empty [cmdk-empty]
Automatically renders when there are no results for the search query.
Loading [cmdk-loading]
You should conditionally render this with progress
while loading asynchronous items.
useCmdk(state => state.selectedField)
Hook that composes useSyncExternalStore
. Pass a function that returns a slice of the command menu state to re-render when that slice changes.
FAQ
Accessible? Yes. Labeling, aria attributes, and DOM ordering tested with Voice Over and Chrome DevTools. Dialog composes an accessible Dialog implementation.
Virtualization? No. Good performance up to 2,000-3,000 items, though. Read below to bring your own.
Filter/sort items manually? Yes. Pass shouldFilter={false}
to Command. Better memory usage and performance, bring your own virtualization this way.
React 18 safe? Yes, required. Uses React 18 hooks like useId
and useSyncExternalStore
.
Unstyled? Yes, use the listed CSS selectors.
Hydration mismatch? Yes. Only render when mounted on client, or use Dialog with open={false}
, which handles this automatically.
React strict mode safe? Yes. Open an issue if you notice a bug.
Weird/wrong behavior? Make sure your Command.Item
has a key
and unique value
.
Concurrent mode safe? Probably not, but concurrent mode is not yet real. Uses risky approaches like manual DOM ordering.
React server component? No, it's a client component.
History
Written in 2019 by Paco (@pacocoursey) to see if a composable combobox API was possible. Used for the Vercel command menu and autocomplete by Rauno (@raunofreiberg) in 2020. Re-written independently in 2022 with a simpler and more performant approach. Ideas from Shu (@shuding_).
use-descendants was extracted from the 2019 version.