Primitives
Command
Command palette (cmdk) with a mono search input.
● LIVE
No results.
Breach Protocol⌘B
Trace Route⌘T
Deploy Daemon⌘D
[ interactive — use the trigger to open ]
"use client";import { CrosshairIcon, RadioIcon, SatelliteIcon } from "lucide-react";import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandShortcut,} from "@/registry/okibi/ui/command";export default function CommandDemo() { return ( <Command className="w-80 max-w-full border border-border-strong"> <CommandInput placeholder="Search ops..." /> <CommandList> <CommandEmpty>No results.</CommandEmpty> <CommandGroup heading="Sector 0x4A2"> <CommandItem> <CrosshairIcon /> Breach Protocol <CommandShortcut>⌘B</CommandShortcut> </CommandItem> <CommandItem> <SatelliteIcon /> Trace Route <CommandShortcut>⌘T</CommandShortcut> </CommandItem> <CommandItem> <RadioIcon /> Deploy Daemon <CommandShortcut>⌘D</CommandShortcut> </CommandItem> </CommandGroup> </CommandList> </Command> );}npx shadcn@latest add https://okibi.cndr.dev/r/command.jsonInstallation
Install the theme first, then add the component:
npx shadcn@latest add https://okibi.cndr.dev/r/command.jsonInstall the required dependencies:
npm install cmdk lucide-reactAdd 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 ]
"use client";import { useState } from "react";import { CrosshairIcon, RadioIcon, SatelliteIcon, TerminalIcon,} from "lucide-react";import { Button } from "@/registry/okibi/ui/button";import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandShortcut,} from "@/registry/okibi/ui/command";export default function CommandDialogDemo() { const [open, setOpen] = useState(false); return ( <> <Button variant="outline-tech" onClick={() => setOpen(true)}> Open palette ⌘K </Button> <CommandDialog open={open} onOpenChange={setOpen}> <CommandInput placeholder="Search ops..." /> <CommandList> <CommandEmpty>No results.</CommandEmpty> <CommandGroup heading="Sector Ops"> <CommandItem onSelect={() => setOpen(false)}> <CrosshairIcon /> Breach Protocol <CommandShortcut>⌘B</CommandShortcut> </CommandItem> <CommandItem onSelect={() => setOpen(false)}> <SatelliteIcon /> Trace Route <CommandShortcut>⌘T</CommandShortcut> </CommandItem> <CommandItem onSelect={() => setOpen(false)}> <RadioIcon /> Deploy Daemon <CommandShortcut>⌘D</CommandShortcut> </CommandItem> <CommandItem onSelect={() => setOpen(false)}> <TerminalIcon /> Open Console </CommandItem> </CommandGroup> </CommandList> </CommandDialog> </> );}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
No matching ops
Scan Subnet⌘S
Open Shell⌘K
Inject Payload⌘I
Clone Node⌘C
Archive Log⌘A
Purge Cache⌘⌫
"use client";import { ArchiveIcon, BanIcon, CopyIcon, RadarIcon, TerminalIcon, TrashIcon,} from "lucide-react";import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut,} from "@/registry/okibi/ui/command";export default function CommandStatesDemo() { return ( <Command className="w-80 max-w-full border border-border-strong"> <CommandInput placeholder="Search ops..." /> <CommandList> <CommandEmpty>No matching ops</CommandEmpty> <CommandGroup heading="Recon"> <CommandItem> <RadarIcon /> Scan Subnet <CommandShortcut>⌘S</CommandShortcut> </CommandItem> <CommandItem> <TerminalIcon /> Open Shell <CommandShortcut>⌘K</CommandShortcut> </CommandItem> <CommandItem disabled> <BanIcon /> Inject Payload <CommandShortcut>⌘I</CommandShortcut> </CommandItem> </CommandGroup> <CommandSeparator /> <CommandGroup heading="Vault"> <CommandItem> <CopyIcon /> Clone Node <CommandShortcut>⌘C</CommandShortcut> </CommandItem> <CommandItem> <ArchiveIcon /> Archive Log <CommandShortcut>⌘A</CommandShortcut> </CommandItem> <CommandItem> <TrashIcon /> Purge Cache <CommandShortcut>⌘⌫</CommandShortcut> </CommandItem> </CommandGroup> </CommandList> </Command> );}Accessibility
- Built on
cmdk: arrow keys move the active item,Enterruns it, and typing filters the list live. - The active row is marked with
data-[selected=true]and washedbg-primaryso the selection is always visible. CommandInputopts out of the global focus ring on purpose — there's a single field and the results list owns the visible selection.CommandDialognests a visually-hiddenDialogTitle/DialogDescriptioninsideDialogContent, so the palette dialog is properly labelled and described.- Use
CommandLoadingfor async results so an in-flight fetch is announced, not a blank or empty list.
Guidelines
Do
- Group results with
CommandGroupand divide sections withCommandSeparatorto keep a long palette scannable. - Always render a
CommandEmptyso a no-match search reads as empty rather than broken. - Wrap async results in
CommandLoadingwhile the query is in flight.
Don't
- Don't render
CommandDialog's title/description outsideDialogContent— Radix needs them inside to wire the dialog's accessible name. - Don't let a long item label and a trailing
CommandShortcutcollide; let the labeltruncateso overflow stays legible. - Don't use a command palette for a handful of fixed options — that's a
SelectorDropdownMenu.