-
Notifications
You must be signed in to change notification settings - Fork 0
React API
Complete API for modern-cmdk/react — the React 19 compound component adapter.
pnpm add modern-cmdk/reactPeer dependencies: react@^19.3.0, @radix-ui/react-dialog@^1.4.4
All components use the "use client" directive and support ref as a prop (React 19 native, no forwardRef).
Root component. Creates the state machine and provides context to all children.
<Command
label="Command palette" // accessible label (required)
filter={(value, search) => 1} // custom filter function (optional)
loop={false} // wrap navigation (optional, default: false)
onValueChange={(v) => {}} // callback when active item changes (optional)
ref={ref} // ref forwarding (optional)
>
{children}
</Command>Search input with combobox semantics (role="combobox").
<Command.Input
placeholder="Search..." // input placeholder
value={search} // controlled value (optional)
onValueChange={(v) => {}} // search change callback (optional)
ref={ref} // ref forwarding (optional)
/>Scrollable results container (role="listbox"). Automatically virtualizes when filteredCount > 100.
<Command.List
ref={ref} // ref forwarding (optional)
>
{children}
</Command.List>Shown when no results match the search query (role="status").
<Command.Empty>No results found.</Command.Empty>Shown during async operations (aria-busy).
<Command.Loading>
{progress && <span>{progress}%</span>}
</Command.Loading>Groups items under a heading (role="group" with aria-labelledby).
<Command.Group
heading="Settings" // group heading text
forceMount={false} // keep mounted when empty (optional)
>
<Command.Item>...</Command.Item>
</Command.Group>Selectable item (role="option" with aria-selected).
<Command.Item
value="settings" // unique value for filtering/matching
keywords={['preferences']} // additional search keywords (optional)
disabled={false} // disable selection (optional)
onSelect={() => {}} // selection callback
forceMount={false} // keep mounted when filtered out (optional)
ref={ref} // ref forwarding (optional)
>
Settings
</Command.Item>Visual separator between groups (role="separator").
<Command.Separator alwaysRender={false} />Renders keyboard shortcut hint inside an item (<kbd> element).
<Command.Item value="save" onSelect={save}>
Save
<Command.Shortcut>Ctrl+S</Command.Shortcut>
</Command.Item>Renders a status badge inside an item (<span> element).
<Command.Item value="experimental">
New Feature
<Command.Badge>Beta</Command.Badge>
</Command.Item>Wraps Command in a Radix UI Dialog with focus trap, portal, and overlay.
<Command.Dialog
open={open}
onOpenChange={setOpen}
label="Command palette"
>
<Command.Input placeholder="Type a command..." />
<Command.List>
<Command.Item value="home" onSelect={() => navigate('/')}>
Home
</Command.Item>
</Command.List>
</Command.Dialog>Features:
-
@starting-styleCSS animations for GPU-composited enter/exit - Focus trap with return-to-trigger on close
- Portal rendering (escapes z-index stacking)
- Overlay with
backdrop-filter: blur() - Escape key to close
- Click outside to close
Subscribes to machine state via useSyncExternalStore. Accepts an optional selector for fine-grained re-renders.
const search = useCommandState((state) => state.search);
const count = useCommandState((state) => state.filteredIds.length);Returns the raw CommandMachine instance from context. Useful for dispatching custom events.
const machine = useCommandMachine();
machine.send({ type: 'PAGE_PUSH', page: 'settings' });Automatic virtualization activates when filteredCount > 100. Configure via <Command.List>:
<Command.List>
{/* Items are automatically virtualized */}
{items.map(item => (
<Command.Item key={item.id} value={item.value}>
{item.label}
</Command.Item>
))}
</Command.List>Manual control:
<Command.List
estimateSize={() => 40} // estimated item height in px
overscan={5} // items to render outside viewport
>
{children}
</Command.List>| Feature | Usage |
|---|---|
ref as prop |
All components accept ref directly, no forwardRef
|
useSyncExternalStore |
Tear-free state subscription |
useTransition |
Non-blocking search updates |
useOptimistic |
Instant active item visual feedback |
"use client" directive |
All components are client-only |
Activity API (<Offscreen>) |
Virtualized item pre-rendering |
The React adapter exposes CSS custom properties for theming:
[data-command-root] {
--command-accent: oklch(0.7 0.15 250);
--command-bg: oklch(0.15 0.01 260);
--command-text: oklch(0.95 0.01 260);
--command-border: oklch(0.3 0.02 260);
--command-radius: 12px;
--command-shadow: 0 16px 70px oklch(0 0 0 / 0.5);
}See Theming for full property reference.
| Attribute | Applied to | Description |
|---|---|---|
[data-command-root] |
Command |
Root container |
[data-command-input] |
Command.Input |
Search input |
[data-command-list] |
Command.List |
Results list |
[data-command-item] |
Command.Item |
Each item |
[data-command-group] |
Command.Group |
Each group |
[data-command-separator] |
Command.Separator |
Separator |
[data-command-empty] |
Command.Empty |
Empty state |
[data-command-loading] |
Command.Loading |
Loading state |
[data-command-item-active] |
Command.Item |
Active/highlighted item |
[data-command-item-disabled] |
Command.Item |
Disabled item |