Command
The Command component allows users to filter a list of commands by typing and to run the one they choose.
When to Use
- as a command palette in a Dialog, for one search over a product’s actions and pages that users open from the keyboard
- for a list of actions that needs a search, in a page or a Popover
When Not to Use
- to choose a value for a form, as a Command list runs an action and has no value (use a Combobox)
- for a few actions on one record (use a Dropdown Menu)
Anatomy
| Element | Usage |
|---|---|
| Search field | Required |
| Group heading | Optional |
| Item | Required |
| Shortcut | Optional |
| Container | Required |
| Separator | Optional |
CommandInput renders an Input Group with a search icon. CommandEmpty is shown in place of the list when no item matches. CommandItem adds a check, which appears when the item has data-checked="true" and no shortcut.
CommandDialog renders its children in a Dialog that has a visually hidden title and description and no close button.
Behavior
The Command component has no trigger and no popup of its own. When it is placed on a page, it is always open. To open it over the page as a command palette, place it in a CommandDialog.
The Command component fills the width and the height of its container. The list has a maximum height of 288px and scrolls when its items are taller.
Content
| String | Rule | Example | Counterexample |
|---|---|---|---|
| Placeholder | Say what the search covers | “Search for a command” | “Search…” |
| Item | Start an action with its verb | “Create invoice” | “New invoice” |
| Empty message | Name what was not found | “No commands found.” | “No results.” |
The hidden title and description of a CommandDialog are set in labels.command: “Command palette” and “Search for a command to run…” by default. To replace them for one CommandDialog, pass title and description. To translate them, use the Summit Provider.
Accessibility
The cmdk library sets the roles and keeps focus in the input. When users press an arrow key or move the pointer, aria-activedescendant on the input points to the highlighted item.
Keyboard
| Key | Result |
|---|---|
| A character | Filters the list and moves the highlight to the first match |
ArrowDown, ArrowUp | Moves the highlight to the next or the previous item. It stops at the ends unless loop is set on Command. |
Ctrl+N or Ctrl+J | Moves the highlight to the next item |
Ctrl+P or Ctrl+K | Moves the highlight to the previous item. To turn off all four, set vimBindings={false} on Command. |
Home, End | Moves the highlight to the first or the last item |
Meta+ArrowUp, Meta+ArrowDown | Moves the highlight to the first or the last item |
Alt+ArrowUp, Alt+ArrowDown | Moves the highlight to the first item of the previous or the next group |
Enter | Runs onSelect on the highlighted item |
Escape | In a CommandDialog, closes the Dialog and returns focus to where it was |
Tab | Moves focus out of an inline list. In a CommandDialog, focus stays in the input. |
Requirements
The search input needs a name so that screen readers can announce it, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires. To provide
one, set label on Command. The cmdk library uses that label to name the input.
The list is named by labels.command.suggestions, which is “Suggestions” by default. To translate it, use the Summit Provider.
Installation
npx shadcn@latest add @summit/commandThe CLI also adds @summit/dialog, @summit/input-group, and @summit/summit-provider.
Usage
You provide what each item does, the shortcut that opens a command palette, and the code that closes the palette after a command has run.
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command';
<Command label="Commands" className="w-96 border">
<CommandInput placeholder="Search for a command" />
<CommandList>
<CommandEmpty>No commands found.</CommandEmpty>
<CommandGroup heading="Create">
<CommandItem onSelect={createInvoice}>Create invoice</CommandItem>
<CommandItem onSelect={logTime}>Log time</CommandItem>
</CommandGroup>
</CommandList>
</Command>;As a Command Palette
To use the Command component as a command palette, keep open in state, toggle it from a shortcut, and set it to false in each onSelect.
import { useEffect, useState } from 'react';
import { Command, CommandDialog, CommandInput, CommandItem, CommandList } from '@/components/ui/command';
const [open, setOpen] = useState(false);
useEffect(() => {
function toggle(event: KeyboardEvent) {
if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
setOpen((current) => !current);
}
}
document.addEventListener('keydown', toggle);
return () => document.removeEventListener('keydown', toggle);
}, []);
<CommandDialog open={open} onOpenChange={setOpen}>
<Command label="Command palette">
<CommandInput placeholder="Search for a command" />
<CommandList>
<CommandItem
onSelect={() => {
setOpen(false);
createInvoice();
}}
>
Create invoice
</CommandItem>
</CommandList>
</Command>
</CommandDialog>;With an Icon and a Shortcut
Place the icon first, with aria-hidden, and the CommandShortcut last. Set value so that the shortcut’s characters aren’t included in the search.
import { CommandItem, CommandShortcut } from '@/components/ui/command';
import { ReceiptIcon } from '@phosphor-icons/react';
<CommandItem value="Create invoice" onSelect={createInvoice}>
<ReceiptIcon aria-hidden />
Create invoice
<CommandShortcut>⌘I</CommandShortcut>
</CommandItem>;Mark the Current Item
To mark the current item with a check at its end, such as the theme in use, set data-checked.
<CommandItem data-checked={theme === 'dark'} onSelect={() => setTheme('dark')}>
Dark
</CommandItem>API Reference
CommandShortcut accepts the props of a span. The other parts, except CommandDialog, accept the props of their matching parts in cmdk. See the cmdk documentation for label, shouldFilter, filter, loop, value, keywords, and onSelect.
CommandDialog
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | labels.command.title | The hidden title of the Dialog |
description | string | labels.command.description | The hidden description of the Dialog |
showCloseButton | boolean | false | Shows the close button of the Dialog |
className | string | None | Classes for the popup of the Dialog |
CommandDialog also accepts the props of Dialog, such as open and onOpenChange.