Command Menu
A keyboard-driven command palette component with global Cmd+K / Ctrl+K shortcut. Built on Radix UI Dialog for accessibility and focus management.
Command Menu Demo
Press ⌘K to open the command menu.
Vertical Variant (Default)
Horizontal Variant
Press ⌘J to open.
Keyboard Shortcuts
- ⌘K – Open vertical command menu
- ⌘J – Open horizontal command menu
- ↑ ↓ – Navigate items
- Enter – Select item
- Tab – Cycle tabs
- Esc – Close menu
Basic Usage
Press Cmd+K (Mac) or Ctrl+K (Windows/Linux) to open the command menu.
import { CommandMenu } from '@/components/CommandMenu'
<CommandMenu.Root onSelect={(value) => console.log(value)}>
<CommandMenu.Content>
<CommandMenu.Search placeholder="Search all commands..." />
<CommandMenu.Tabs defaultValue="home">
<CommandMenu.Tab value="home">Home</CommandMenu.Tab>
<CommandMenu.Tab value="dashboard" badge={5}>Dashboard</CommandMenu.Tab>
</CommandMenu.Tabs>
<CommandMenu.Divider />
<CommandMenu.Group label="Actions">
<CommandMenu.Item value="settings" icon={<SettingsIcon />}>
Settings
</CommandMenu.Item>
<CommandMenu.Item value="profile" icon={<UserIcon />}>
Profile
</CommandMenu.Item>
</CommandMenu.Group>
<CommandMenu.Footer />
</CommandMenu.Content>
</CommandMenu.Root>Variants
The Command Menu supports two layout variants.
Vertical (Default)
A compact 500px wide modal with horizontal tabs.
<CommandMenu.Root variant="vertical">
<CommandMenu.Content>
{/* ... */}
</CommandMenu.Content>
</CommandMenu.Root>Horizontal
A wider 895px modal with vertical sidebar tabs.
<CommandMenu.Root variant="horizontal">
<CommandMenu.Content>
<CommandMenu.Search />
<div className="flex flex-1">
{/* Sidebar tabs */}
<div className="border-r border-bg-surface p-4">
<CommandMenu.Tabs defaultValue="home">
<CommandMenu.Tab value="home">Home</CommandMenu.Tab>
<CommandMenu.Tab value="dashboard">Dashboard</CommandMenu.Tab>
</CommandMenu.Tabs>
</div>
{/* Main content */}
<div className="flex-1 p-4">
<CommandMenu.Group label="Commands">
{/* ... items */}
</CommandMenu.Group>
</div>
</div>
<CommandMenu.Footer showNavigation showHelp />
</CommandMenu.Content>
</CommandMenu.Root>Recent Items
Use CommandMenu.Tag for removable recent items.
<CommandMenu.Group label="Recent" showClear onClear={handleClear}>
<div className="flex flex-wrap gap-2">
<CommandMenu.Tag icon={<FileIcon />} onRemove={() => remove('doc1')}>
Q2 Strategy.doc
</CommandMenu.Tag>
<CommandMenu.Tag icon={<FolderIcon />} onRemove={() => remove('project1')}>
Project Alpha
</CommandMenu.Tag>
</div>
</CommandMenu.Group>Tab Filtering
Items can be assigned to specific tabs using the tabId prop.
<CommandMenu.Tabs defaultValue="home">
<CommandMenu.Tab value="home">Home</CommandMenu.Tab>
<CommandMenu.Tab value="settings">Settings</CommandMenu.Tab>
</CommandMenu.Tabs>
<CommandMenu.Group label="Actions">
{/* Only visible when "home" tab is active */}
<CommandMenu.Item value="dashboard" tabId="home">
Dashboard
</CommandMenu.Item>
{/* Only visible when "settings" tab is active */}
<CommandMenu.Item value="account" tabId="settings">
Account Settings
</CommandMenu.Item>
</CommandMenu.Group>Custom Keyboard Shortcut
Change the default Cmd+K shortcut using the shortcutKey prop.
{/* Opens with Cmd+J instead of Cmd+K */}
<CommandMenu.Root shortcutKey="j">
<CommandMenu.Content>
{/* ... */}
</CommandMenu.Content>
</CommandMenu.Root>Controlled Mode
Control the open state externally.
const [open, setOpen] = useState(false)
<CommandMenu.Root open={open} onOpenChange={setOpen}>
<CommandMenu.Content>
{/* ... */}
</CommandMenu.Content>
</CommandMenu.Root>
{/* Open programmatically */}
<button onClick={() => setOpen(true)}>Open Menu</button>Keyboard Navigation
| Key | Action |
|---|---|
Cmd+K / Ctrl+K | Open/close command menu |
Arrow Up/Down | Navigate through items |
Enter | Select highlighted item |
Tab / Shift+Tab | Cycle through tabs |
Escape | Close menu |
Accessibility
- Built on Radix UI Dialog for robust focus management
- Full keyboard navigation support
- Proper ARIA attributes (
role="dialog",aria-modal) - Focus trap within the modal
- Auto-focus on search input when opened
- Screen reader friendly item descriptions
API Reference
CommandMenu.Root Props
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | 'vertical' | 'horizontal' | 'vertical' | Layout variant |
| open | boolean | - | Controlled open state |
| defaultOpen | boolean | false | Default open state |
| onOpenChange | (open: boolean) => void | - | Callback when open state changes |
| onSelect | (value: string) => void | - | Callback when item is selected |
| shortcutKey | string | 'k' | Keyboard shortcut key (used with Cmd/Ctrl) |
| defaultTab | string | - | Default active tab |
CommandMenu.Content Props
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | - | Additional CSS classes |
CommandMenu.Search Props
| Prop | Type | Default | Description |
|---|---|---|---|
| placeholder | string | 'Search all commands...' | Placeholder text |
| showKbd | boolean | true | Show keyboard shortcut indicator |
| showFilter | boolean | true | Show filter icon button |
| onFilterClick | () => void | - | Filter button click handler |
CommandMenu.Tabs Props
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | string | - | Default active tab value |
CommandMenu.Tab Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | Required | Unique value for this tab |
| badge | number | - | Badge count to display |
CommandMenu.Group Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | - | Section label |
| showClear | boolean | false | Show clear button |
| onClear | () => void | - | Clear button click handler |
CommandMenu.Item Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | Required | Unique value for this item |
| icon | React.ReactNode | - | Icon element |
| tabId | string | - | Tab this item belongs to (for filtering) |
| showArrow | boolean | false | Show arrow icon (for navigation items) |
| showEnter | boolean | true | Show enter icon when highlighted |
| disabled | boolean | false | Disable this item |
CommandMenu.Tag Props
| Prop | Type | Default | Description |
|---|---|---|---|
| icon | React.ReactNode | - | Icon element |
| onRemove | () => void | - | Remove button click handler |
CommandMenu.Footer Props
| Prop | Type | Default | Description |
|---|---|---|---|
| showNavigation | boolean | true | Show navigation arrows hint |
| showHelp | boolean | Auto | Show help section (defaults based on variant) |
| helpText | string | 'Contact support' | Help link text |
| onHelpClick | () => void | - | Help link click handler |