Skip to content

React API

ABCrimson edited this page Mar 11, 2026 · 2 revisions

React API Reference

Complete API for modern-cmdk/react — the React 19 compound component adapter.


Installation

pnpm add modern-cmdk/react

Peer dependencies: react@^19.3.0, @radix-ui/react-dialog@^1.4.4


Compound Components

All components use the "use client" directive and support ref as a prop (React 19 native, no forwardRef).

<Command>

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>

<Command.Input>

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)
/>

<Command.List>

Scrollable results container (role="listbox"). Automatically virtualizes when filteredCount > 100.

<Command.List
  ref={ref}                     // ref forwarding (optional)
>
  {children}
</Command.List>

<Command.Empty>

Shown when no results match the search query (role="status").

<Command.Empty>No results found.</Command.Empty>

<Command.Loading>

Shown during async operations (aria-busy).

<Command.Loading>
  {progress && <span>{progress}%</span>}
</Command.Loading>

<Command.Group>

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>

<Command.Item>

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>

<Command.Separator>

Visual separator between groups (role="separator").

<Command.Separator alwaysRender={false} />

<Command.Shortcut>

Renders keyboard shortcut hint inside an item (<kbd> element).

<Command.Item value="save" onSelect={save}>
  Save
  <Command.Shortcut>Ctrl+S</Command.Shortcut>
</Command.Item>

<Command.Badge>

Renders a status badge inside an item (<span> element).

<Command.Item value="experimental">
  New Feature
  <Command.Badge>Beta</Command.Badge>
</Command.Item>

Dialog Component

<Command.Dialog>

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-style CSS 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

Hooks

useCommandState(selector)

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);

useCommandMachine()

Returns the raw CommandMachine instance from context. Useful for dispatching custom events.

const machine = useCommandMachine();
machine.send({ type: 'PAGE_PUSH', page: 'settings' });

Virtualization

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>

React 19 Features Used

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

CSS Custom Properties

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.


Data Attributes

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

Clone this wiki locally