Skip to content
Primitives

Command

Command palette (cmdk) with a mono search input.

● LIVE

[ interactive — use the trigger to open ]

npx shadcn@latest add https://okibi.cndr.dev/r/command.json

Installation

Install the theme first, then add the component:

npx shadcn@latest add https://okibi.cndr.dev/r/command.json

Install the required dependencies:

npm install cmdk lucide-react

Add the okibi building blocks it composes: dialog.

Copy the source from the Code tab above into components/ui/command.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.

Usage

import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"

<Command>
  <CommandInput placeholder="Search…" />
  <CommandList>
    <CommandEmpty>No results.</CommandEmpty>
    <CommandGroup>
      <CommandItem>Open channel</CommandItem>
    </CommandGroup>
  </CommandList>
</Command>

Anatomy

<Command>
  <CommandInput />              {/* mono search field */}
  <CommandList>
    <CommandEmpty />            {/* shown when nothing matches */}
    <CommandGroup>
      <CommandItem>
        Run <CommandShortcut />  {/* trailing mono hotkey */}
      </CommandItem>
    </CommandGroup>
    <CommandSeparator />
  </CommandList>
</Command>

Examples

Command dialog

Mount the palette inside a dialog (open it with a button or a ⌘K shortcut) for an app-wide command launcher.

● LIVE

[ interactive — use the trigger to open ]

Grouped & states

An inline palette exercising the full surface — grouped items split by a separator, a disabled row, keyboard shortcuts, and a no-results empty state.

● LIVE

Accessibility

  • Built on cmdk: arrow keys move the active item, Enter runs it, and typing filters the list live.
  • The active row is marked with data-[selected=true] and washed bg-primary so the selection is always visible.
  • CommandInput opts out of the global focus ring on purpose — there's a single field and the results list owns the visible selection.
  • CommandDialog nests a visually-hidden DialogTitle/DialogDescription inside DialogContent, so the palette dialog is properly labelled and described.
  • Use CommandLoading for async results so an in-flight fetch is announced, not a blank or empty list.

Guidelines

Do

  • Group results with CommandGroup and divide sections with CommandSeparator to keep a long palette scannable.
  • Always render a CommandEmpty so a no-match search reads as empty rather than broken.
  • Wrap async results in CommandLoading while the query is in flight.

Don't

  • Don't render CommandDialog's title/description outside DialogContent — Radix needs them inside to wire the dialog's accessible name.
  • Don't let a long item label and a trailing CommandShortcut collide; let the label truncate so overflow stays legible.
  • Don't use a command palette for a handful of fixed options — that's a Select or DropdownMenu.

On this page