← All components
navigation / stable

Command

Searchable action list (cmdk) and the ⌘K palette (CommandDialog).

LIVE PREVIEW
Loading preview…

When to use

  • The global ⌘K palette (open it with `useShortcut("mod+k")`).
  • "Jump to" and "move to" pickers over many targets.

Consider an alternative

  • Choosing a form value — use ComboBox.
  • A handful of actions — use Menu.

Import

import { Command } from '@revido-llc/kit';

Keyboard interaction

  • Type — filter (items also match their keywords)
  • ArrowUp / ArrowDown (or Ctrl+N / Ctrl+P) — move
  • Home / End — first / last item
  • Enter — run the highlighted item
  • Escape — close the dialog

Props

Props documented by the Kit. Refer to the TypeScript types for the complete interface, including inherited props.

childrenReactNode—
classNamestring—

Related exports

CommandDialog, CommandInput, CommandList, CommandGroup, CommandItem, CommandLoading, CommandEmpty, CommandSeparator

Examples

Inline

A "jump to" picker in the page. Groups, keywords, shortcut hints and the empty state; the list scrolls inside itself.

<Command label="Commands">
  <CommandInput placeholder="Type a command or search…" />
  <CommandList>
    <CommandEmpty>No results.</CommandEmpty>
    <CommandGroup heading="Navigate">
      <CommandItem
        leading={{ kind: "icon", icon: <FolderKanban /> }}
        shortcut="G P"
        keywords={["work", "tasks"]}
        onSelect={() => router.push("/projects")}
      >
        Projects
      </CommandItem>
    </CommandGroup>
  </CommandList>
</Command>

Palette dialog

Medium dialog, top-aligned at 15vh; the input takes focus, Enter runs the item and the palette closes. Bind ⌘K / Ctrl+K with `useShortcut` as in the code (the /design hub search does); the live demo leaves it unbound so it doesn't fight the hub's own palette.

const [open, setOpen] = useState(false);
useShortcut("mod+k", () => setOpen((o) => !o));

<Button variant="outline" onPress={() => setOpen(true)}>
  Search <KbdGroup shortcut="mod+k" />
</Button>
<CommandDialog isOpen={open} onOpenChange={setOpen} label="Search">
  <CommandInput placeholder="Type a command or search…" />
  <CommandList>
    <CommandEmpty>No results.</CommandEmpty>
    <CommandGroup heading="Navigate">
      <CommandItem onSelect={() => router.push("/projects")}>Projects</CommandItem>
    </CommandGroup>
  </CommandList>
</CommandDialog>

Your own filtering

`shouldFilter={false}` when results come from a server or a custom ranking: control the input with `value` / `onValueChange` and render only the matches. `CommandLoading` covers the wait; `CommandEmpty` still shows when nothing is rendered.

<Command label="Search" shouldFilter={false}>
  <CommandInput value={query} onValueChange={setQuery} placeholder="Search projects…" />
  <CommandList>
    {isLoading ? <CommandLoading>Searching…</CommandLoading> : null}
    {!isLoading && <CommandEmpty>No projects match.</CommandEmpty>}
    {results.map((p) => (
      <CommandItem key={p.id} value={p.id} onSelect={() => open(p)}>{p.name}</CommandItem>
    ))}
  </CommandList>
</Command>

Literal anatomy 1

Static component anatomy; bind events in the consuming app.

<Command><CommandInput /><CommandList><CommandEmpty>No results.</CommandEmpty><CommandGroup><CommandItem value="draft">Open draft</CommandItem></CommandGroup><CommandSeparator /><CommandLoading label="Loading choices" /></CommandList></Command>

Literal anatomy 2

Static component anatomy; bind events in the consuming app.

<CommandDialog label="Find a record"><CommandInput /><CommandList><CommandItem value="draft">Open draft</CommandItem></CommandList></CommandDialog>

Related components