Skip to content
Components

Command

Find and run an action by typing. Use Command inline or CommandDialog for a palette, with grouped results and keyboard navigation.

Preview

    • New project⌘ N
    • Search projects
    • Settings
    • Billing

Props

  • placeholder
  • emptyText
  • defaultSearch
  • disabled
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

    • Create project
    • Archive project
    • Edit profile
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

    • Appearance
    • Notifications
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

NameTypeValuesDefaultDescription
label requiredstring--Accessible name of the search input and results list.
placeholderstring-Search actions…Visible hint in the search input.
emptyTextstring-No results found.Status shown when no command matches the query.
searchstring--Controlled search text. The parent updates it through onSearchChange.
defaultSearchstring-Initial search text for an uncontrolled Command.
onSearchChangefunction--Called with the new search text whenever the user types.
loopboolean-trueWrap arrow navigation from the last enabled result to the first.
openboolean--Controlled open state of CommandDialog.
defaultOpenboolean-falseInitial open state of an uncontrolled CommandDialog.
onOpenChangefunction--Called when CommandDialog opens or closes.
heading requiredstring--Visible and accessible heading of CommandGroup.
value requiredstring--Unique CommandItem identifier passed to onSelect. It is not a persisted form selection.
keywordsnode--An array of additional search words on CommandItem.
leadingIconnode--Decorative CommandItem icon. Use a regular 16px icon.
shortcutnode--Keyboard hint after an item. Displays text only; does not register a shortcut.
disabledboolean-falseA disabled CommandItem stays visible but cannot highlight or activate.
onSelectfunction--CommandItem callback receiving its value. CommandDialog closes after activation.
textValuestring--Searchable label for CommandItem when children contain a custom node.
title requiredstring--CommandDialog uses the title prop to name its dialog. Required on CommandDialog, absent on inline Command.
descriptionstring--CommandDialog uses the description prop for an optional accessible description.

Anatomy

PartDescription
rootAn enabled command or a disabled result.
controlSearch input with combobox semantics.
placeholderHint shown in the empty search input.
listScrollable result list.
iconDecorative icon before a command label.
groupLabelVisible heading of a result group.
separatorDecorative line between visible groups.
emptyStatus text when no command matches.
shortcutA mono keyboard hint using Kbd.
contentInline raised panel containing its search field and results.

Accessibility

Role: combobox

KeysAction
ArrowDown / ArrowUpMove the highlight through enabled visible commands without leaving the search field.
Home / EndHighlight the first or last enabled visible command.
EnterActivate the highlighted command once; never activate while composing text.
EscapeClose CommandDialog and restore focus to the opener. Inline Command leaves Escape to its owner.
Tab / Shift+TabFollow 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.json

This 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").