Components
Command menu for search and quick actions, built on cmdk.
Playground
heading, and CommandSeparator divides groups. Typing filters items automatically — matching happens against each item's text content.import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
} from "@workspace/ui/components/command"
<Command className="max-w-sm rounded-lg border">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>Profile</CommandItem>
<CommandItem>Billing</CommandItem>
<CommandItem>Settings</CommandItem>
</CommandGroup>
</CommandList>
</Command>open / onOpenChange and toggle it from a global ⌘K listener. Run an action from onSelect on each item.or press ⌘K
Search for a command to run...
const [open, setOpen] = React.useState(false)
React.useEffect(() => {
function down(event: KeyboardEvent) {
if (event.key === "k" && (event.metaKey || event.ctrlKey)) {
event.preventDefault()
setOpen((current) => !current)
}
}
document.addEventListener("keydown", down)
return () => document.removeEventListener("keydown", down)
}, [])
<CommandDialog open={open} onOpenChange={setOpen}>
<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem onSelect={() => setOpen(false)}>
<CalendarBlankIcon />
<span>Calendar</span>
</CommandItem>
{/* ... */}
</CommandGroup>
</CommandList>
</Command>
</CommandDialog>gap-2 and size any svg to size-4, so an icon followed by a span just works. CommandShortcut pushes itself to the end with ms-auto to display the keyboard shortcut — it is presentational only, the key handling is up to you. Disabled items skip filtering, pointer and keyboard selection.<Command className="max-w-sm rounded-lg border">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>
<CalendarBlankIcon />
<span>Calendar</span>
</CommandItem>
<CommandItem>
<SmileyIcon />
<span>Search Emoji</span>
</CommandItem>
<CommandItem disabled>
<CalculatorIcon />
<span>Calculator</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>
<UserIcon />
<span>Profile</span>
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCardIcon />
<span>Billing</span>
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
<CommandItem>
<GearIcon />
<span>Settings</span>
<CommandShortcut>⌘S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>max-h-72 and scrolls beyond it, with scroll-py-1 keeping the selected item clear of the edges as you arrow through. Override the cap with a max-h-* class on CommandList.<Command className="max-w-sm rounded-lg border">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Navigation">
<CommandItem>
<HouseIcon />
<span>Home</span>
<CommandShortcut>⌘H</CommandShortcut>
</CommandItem>
{/* ... */}
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Actions">{/* ... */}</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Account">{/* ... */}</CommandGroup>
</CommandList>
</Command>dir="rtl" on the Command root.<Command dir="rtl" className="max-w-sm rounded-lg border">
<CommandInput placeholder="اكتب أمرًا أو ابحث..." />
<CommandList>
<CommandEmpty>لم يتم العثور على نتائج.</CommandEmpty>
<CommandGroup heading="اقتراحات">
<CommandItem>التقويم</CommandItem>
<CommandItem>البحث عن الرموز التعبيرية</CommandItem>
<CommandItem disabled>الآلة الحاسبة</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="الإعدادات">
<CommandItem>
الملف الشخصي
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
الفوترة
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>role="combobox" pointing at a role="listbox" list whose items are role="option", with selection tracked through aria-activedescendant. Arrow keys (plus Home / End) move the selection, Enter runs the item's onSelect, and Escape closes CommandDialog. Name the menu with the label prop — CommandDialog already provides an sr-only title and description you can override.<Command label="Command palette">{/* inline usage */}</Command>
<CommandDialog
title="Command Palette"
description="Search for a command to run..."
>
{/* rendered as sr-only DialogTitle / DialogDescription */}
</CommandDialog>cmdk: Command as the stateful root, CommandInput (an InputGroup with a built-in search icon), CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut, and CommandDialog composing the whole menu into a Dialog. Filtering, sorting, and selection state all live in the root — items register themselves automatically. All parts accept their underlying element props.| Component | Prop | Default |
|---|---|---|
| Command | value?: string, onValueChange?: (value: string) => void, defaultValue?: string | — |
| Command | loop?: boolean, shouldFilter?: boolean, filter?: (value, search, keywords) => number | false / true |
| CommandDialog | title?: string, description?: string, showCloseButton?: boolean, ...Dialog props | showCloseButton: false |
| CommandGroup | heading?: ReactNode, value?: string | — |
| CommandItem | value?: string, keywords?: string[], disabled?: boolean, onSelect?: (value: string) => void | — |
<Command data-slot="command" /> <CommandInput data-slot="command-input" /> <CommandList data-slot="command-list" /> <CommandEmpty data-slot="command-empty" /> <CommandGroup data-slot="command-group" /> <CommandItem data-slot="command-item" /> <CommandShortcut data-slot="command-shortcut" /> <CommandSeparator data-slot="command-separator" />
Tokens used
13 design tokens consumed by the Command component.
--popover
Popover
--popover-foreground
Popover Foreground
--foreground
Foreground
--muted
Muted
--muted-foreground
Muted Foreground
--input
Input
--border
Border
--text-sm
Text Small (14px)
--text-xs
Text Extra Small (12px)
--radius-sm
Radius 0.6× (6px)
--radius-lg
Radius 1× (10px)
--radius-xl
Radius 1.4× (14px)
--spacing
Spacing unit (4px)