Components
Command
Find and run an action by typing. Use Command inline or CommandDialog for a palette, with grouped results and keyboard navigation.
Preview
import { IconPlus, IconSearch, IconSettings } from "@tabler/icons-react"
import { Command, CommandGroup, CommandItem, CommandSeparator, CommandShortcut } from "@/components/ui/command"
const selectCommand = (value: string) => { /* Run the selected action. */ }
<Command label="Search commands" className="w-full max-w-md">
<CommandGroup heading="Workspace">
<CommandItem value="new-project" keywords={["create"]} leadingIcon={<IconPlus size={16} weight="regular" />} onSelect={selectCommand} shortcut={<CommandShortcut aria-label="Command N">⌘ N</CommandShortcut>}>New project</CommandItem>
<CommandItem value="search-projects" leadingIcon={<IconSearch size={16} weight="regular" />} onSelect={selectCommand}>Search projects</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Account">
<CommandItem value="settings" leadingIcon={<IconSettings size={16} weight="regular" />} onSelect={selectCommand}>Settings</CommandItem>
<CommandItem value="billing" disabled onSelect={selectCommand}>Billing</CommandItem>
</CommandGroup>
</Command>Usage
When to use
- Find and run actions from a searchable list, inline or in a dialog.
- Let users navigate to a destination by searching its name or keywords.
When not to use
- Pick a form value from a searchable list. Use Combobox.
- A short fixed menu with no search. Use DropdownMenu.
- Registering global shortcuts. Add the handler in your application.
Examples
Workspace actions
import { Command, CommandGroup, CommandItem, CommandSeparator } from "@/components/ui/command"
const selectCommand = (value: string) => { /* Run the selected action. */ }
<Command label="Find a workspace action" placeholder="Search workspace…">
<CommandGroup heading="Workspace">
<CommandItem value="create" keywords={["new", "add"]} onSelect={selectCommand}>Create project</CommandItem>
<CommandItem value="archive" disabled>Archive project</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Account">
<CommandItem value="profile" onSelect={selectCommand}>Edit profile</CommandItem>
</CommandGroup>
</Command>In a dialog
The parent owns the open state and the action handlers. Closing returns focus to the button.
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Command, CommandDialog, CommandItem } from "@/components/ui/command"
const [commandOpen, setCommandOpen] = useState(false)
const openCommand = () => setCommandOpen(true)
const selectCommand = (value: string) => { /* Run the selected action. */ }
<div>
<Button variant="secondary" onClick={openCommand}>Open commands</Button>
<CommandDialog title="Workspace actions" open={commandOpen} onOpenChange={setCommandOpen}>
<Command label="Find an action">
<CommandItem value="create" onSelect={selectCommand}>Create project</CommandItem>
<CommandItem value="profile" onSelect={selectCommand}>Edit profile</CommandItem>
</Command>
</CommandDialog>
</div>Custom search words
import { Command, CommandGroup, CommandItem } from "@/components/ui/command"
const selectCommand = (value: string) => { /* Run the selected action. */ }
<Command label="Find a setting" emptyText="No settings match.">
<CommandGroup heading="Settings">
<CommandItem value="appearance" textValue="Appearance" keywords={["theme", "dark", "light"]} onSelect={selectCommand}>Appearance</CommandItem>
<CommandItem value="notifications" onSelect={selectCommand}>Notifications</CommandItem>
</CommandGroup>
</Command>Do and don't
Do
- Use short verb-led labels and organize related actions into groups.
- Provide textValue for a custom label and keywords for alternative names.
- Let the application register its own global shortcut and handle action side effects.
Don't
- Do not use Command to submit a form value; use Combobox.
- Do not use live remote search or nested command pages in this version.
- Do not present a shortcut hint for a shortcut the application does not implement.
Props
| Name | Type | Values | Default | Description |
|---|---|---|---|---|
| label required | string | - | - | Accessible name of the search input and results list. |
| placeholder | string | - | Search actions… | Visible hint in the search input. |
| emptyText | string | - | No results found. | Status shown when no command matches the query. |
| search | string | - | - | Controlled search text. The parent updates it through onSearchChange. |
| defaultSearch | string | - | Initial search text for an uncontrolled Command. | |
| onSearchChange | function | - | - | Called with the new search text whenever the user types. |
| loop | boolean | - | true | Wrap arrow navigation from the last enabled result to the first. |
| open | boolean | - | - | Controlled open state of CommandDialog. |
| defaultOpen | boolean | - | false | Initial open state of an uncontrolled CommandDialog. |
| onOpenChange | function | - | - | Called when CommandDialog opens or closes. |
| heading required | string | - | - | Visible and accessible heading of CommandGroup. |
| value required | string | - | - | Unique CommandItem identifier passed to onSelect. It is not a persisted form selection. |
| keywords | node | - | - | An array of additional search words on CommandItem. |
| leadingIcon | node | - | - | Decorative CommandItem icon. Use a regular 16px icon. |
| shortcut | node | - | - | Keyboard hint after an item. Displays text only; does not register a shortcut. |
| disabled | boolean | - | false | A disabled CommandItem stays visible but cannot highlight or activate. |
| onSelect | function | - | - | CommandItem callback receiving its value. CommandDialog closes after activation. |
| textValue | string | - | - | Searchable label for CommandItem when children contain a custom node. |
| title required | string | - | - | CommandDialog uses the title prop to name its dialog. Required on CommandDialog, absent on inline Command. |
| description | string | - | - | CommandDialog uses the description prop for an optional accessible description. |
Anatomy
| Part | Description |
|---|---|
| root | An enabled command or a disabled result. |
| control | Search input with combobox semantics. |
| placeholder | Hint shown in the empty search input. |
| list | Scrollable result list. |
| icon | Decorative icon before a command label. |
| groupLabel | Visible heading of a result group. |
| separator | Decorative line between visible groups. |
| empty | Status text when no command matches. |
| shortcut | A mono keyboard hint using Kbd. |
| content | Inline raised panel containing its search field and results. |
Accessibility
Role: combobox
| Keys | Action |
|---|---|
| ArrowDown / ArrowUp | Move the highlight through enabled visible commands without leaving the search field. |
| Home / End | Highlight the first or last enabled visible command. |
| Enter | Activate the highlighted command once; never activate while composing text. |
| Escape | Close CommandDialog and restore focus to the opener. Inline Command leaves Escape to its owner. |
| Tab / Shift+Tab | Follow normal focus order inline; stay inside the dialog when modal. |
- label is required and names both the search field and listbox.
- aria-activedescendant references only an enabled mounted option. aria-selected follows the current highlight.
- Each CommandGroup is named by its heading. Disabled items are announced as disabled.
- CommandDialog requires title and focuses the search field on open. It resets uncontrolled search on close.
- Use unique item values and plain non-interactive content. Actions belong in onSelect; do not nest links or buttons inside an option.
Install
npx shadcn add https://werewolf-ui.vercel.app/r/command.jsonThis also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").