Command
A searchable command menu with keyboard navigation.
Installation
npx shadcn@latest add @redpanda/commandpnpm dlx shadcn@latest add @redpanda/commandyarn dlx shadcn@latest add @redpanda/commandbunx shadcn@latest add @redpanda/commandnubx shadcn@latest add @redpanda/commandaube dlx shadcn@latest add @redpanda/commandWhen to use
Use this decision tree to determine when to use the Command component:
Usage
import { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CommandSub, CommandSubTrigger, CommandSubContent, SimpleCommand,} from '@/components/ui/command';<Command> <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>Surface variants
Use variant="standalone" for the rounded, bordered panel shown in the examples instead
of adding border, radius, and shadow classes at the call site. The default elevated
variant retains its existing, smaller corner radius. minimal and dialog omit the
elevated border and shadow recipe. CommandDialog selects dialog for its inner command.
Examples
Simple Command
A higher-level component that provides a simplified API for creating command menus.
SimpleCommand Props
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder |
string |
"Type a command or search..." |
Input placeholder text |
emptyMessage |
string |
"No results found." |
Message shown when no results |
groups |
Array<CommandGroup> |
- | Array of command groups (required) |
size |
'sm' | 'md' | 'lg' | 'full' |
'md' |
Command size variant |
className |
string |
- | Additional CSS classes |
CommandGroup Interface
interface CommandGroup { heading?: string; items: CommandItem[];}
interface CommandItem { icon?: React.ReactNode; label: string; shortcut?: string; disabled?: boolean; onSelect?: () => void;}Usage
import { SimpleCommand } from '@/components/ui/command';
const commandGroups = [ { heading: 'Actions', items: [ { icon: <Calendar />, label: 'Calendar', shortcut: '⌘C', onSelect: () => console.log('Calendar selected'), }, { icon: <Settings />, label: 'Settings', disabled: true, onSelect: () => console.log('Settings selected'), }, ], },];
<SimpleCommand groups={commandGroups} placeholder="Search commands..." emptyMessage="No commands found." />;With Icons
With Footer
Loading State
Result Breadcrumbs
Dialog
To show the command menu in a dialog, use the <CommandDialog /> component.
CommandDialog accepts a showCloseButton prop that is forwarded to the underlying DialogContent. It defaults to true (a close button is rendered), which differs from shadcn/ui where it defaults to false. Pass showCloseButton={false} to hide the close button.
export function CommandMenu() { const [open, setOpen] = React.useState(false); const invokingControl = React.useRef<HTMLElement | null>(null);
React.useEffect( function bindPaletteShortcut() { const down = (e: KeyboardEvent) => { if (e.key === 'k' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); if (!open) { const activeControl = document.activeElement; invokingControl.current = activeControl instanceof HTMLElement ? activeControl : null; } setOpen((isOpen) => !isOpen); } }; document.addEventListener('keydown', down); return () => document.removeEventListener('keydown', down); }, [open], );
return ( <CommandDialog finalFocus={invokingControl} open={open} onOpenChange={setOpen}> <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> </CommandList> </CommandDialog> );}For a triggerless keyboard shortcut, capture the focused control before opening and pass its ref as
finalFocus, as above. CommandDialog forwards this public focus destination to the underlying
dialog popup; closing returns focus to that control.
Pass props for the inner Command through commandProps, such as a custom filter when cmdk’s
default scoring ranks the wrong entry first. Its className merges with the owned dialog recipe. CommandDialog always uses variant="dialog"; the contradictory commandProps.variant override is removed. Keep size, filter, loop, shouldFilter, and other inner command props as needed.
<CommandDialog commandProps={{ filter: rankExactMatchesFirst }} onOpenChange={setOpen} open={open}> {/* ... */}</CommandDialog>Submenu
Use CommandSub, CommandSubTrigger, and CommandSubContent to create nested command menus that open as a popover to the right of the trigger item.
function CommandWithSubmenu() { const [labelOpen, setLabelOpen] = React.useState(false);
return ( <Command> <CommandInput placeholder="Type a command or search..." /> <CommandList> <CommandGroup heading="Actions"> <CommandItem>Search</CommandItem> <CommandSub open={labelOpen} onOpenChange={setLabelOpen}> <CommandSubTrigger>Apply Label</CommandSubTrigger> <CommandSubContent> <Command> <CommandInput placeholder="Filter labels..." /> <CommandList> <CommandEmpty>No labels found.</CommandEmpty> <CommandGroup> <CommandItem>Bug</CommandItem> <CommandItem>Feature</CommandItem> <CommandItem>Enhancement</CommandItem> </CommandGroup> </CommandList> </Command> </CommandSubContent> </CommandSub> </CommandGroup> </CommandList> </Command> );}Submenu Props
CommandSub - Root wrapper that manages submenu state with a Popover.
| Prop | Type | Description |
|---|---|---|
open |
boolean |
Whether the submenu is open |
onOpenChange |
(open: boolean) => void |
Callback when open state changes |
children |
ReactNode |
CommandSubTrigger and CommandSubContent |
CommandSubTrigger - Item that opens the submenu when selected. Renders a chevron icon on the right.
| Prop | Type | Default | Description |
|---|---|---|---|
inset |
boolean? |
false |
Indent the trigger with left padding |
className |
string? |
— | Additional CSS classes |
Inherits all props from CommandItem.
CommandSubContent - Popover content for the nested command list. Opens to the right of the trigger.
| Prop | Type | Description |
|---|---|---|
className |
string? |
Additional CSS classes |
children |
ReactNode |
Nested Command with CommandList |
Combobox
You can use the <Command /> component as a combobox. See the Combobox page for more information.