Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Components

Free

Command for React

Filter a palette or jump menu as people type, instead of reading every action. For React with Base UI, when the job is to run a command, not to store a form value.

Framework
UI library

A command menu narrows its actions as you type.

Use it to run an action or jump to a place. If the list is a form value you must store, use a Combobox. In React, Base UI filters the collection you passed in.

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

Anatomy

Command anatomy: root, input, group label, list, item, shortcut
CommandRoot
├── CommandClearTrigger
├── CommandContent
├── CommandControl
├── CommandInput
├── CommandItem
│   ├── CommandGroup
│   │   └── CommandGroupLabel
│   ├── CommandItemIndicator
│   └── CommandItemText
├── CommandLabel
├── CommandList
├── CommandPositioner
└── CommandTrigger

Usage

import {
  CalculatorIcon, CalendarIcon, CreditCardIcon, SettingsIcon, SmileIcon,
  UserIcon,
} from "lucide-react";
import {
  Command, CommandEmpty, CommandGroup, CommandInput, CommandItem,
  CommandList, CommandSeparator, CommandShortcut,
} from "@/components/ui/command";
const CommandDemo = () => (
  <Command className="max-w-sm rounded-lg border">
    <CommandInput placeholder="Type a command or search..." />
    <CommandList>
      <CommandEmpty>No results found.</CommandEmpty>
      <CommandGroup heading="Suggestions">
        <CommandItem>
          <CalendarIcon aria-hidden="true" />
          <span>Calendar</span>
        </CommandItem>
        <CommandItem>
          <SmileIcon aria-hidden="true" />
          <span>Search Emoji</span>
        </CommandItem>
        <CommandItem disabled>
          <CalculatorIcon aria-hidden="true" />
          <span>Calculator</span>
        </CommandItem>
      </CommandGroup>
      <CommandSeparator />
      <CommandGroup heading="Settings">
        <CommandItem>
          <UserIcon aria-hidden="true" />
          <span>Profile</span>
          <CommandShortcut>⌘P</CommandShortcut>
        </CommandItem>
        <CommandItem>
          <CreditCardIcon aria-hidden="true" />
          <span>Billing</span>
          <CommandShortcut>⌘B</CommandShortcut>
        </CommandItem>
        <CommandItem>
          <SettingsIcon aria-hidden="true" />
          <span>Settings</span>
          <CommandShortcut>⌘S</CommandShortcut>
        </CommandItem>
      </CommandGroup>
    </CommandList>
  </Command>
);

Accessibility

Arrow Down
Move down.
Arrow Up
Move up.
Home
Go to the start.
End
Go to the end.
Enter
Activate the focused item.
Escape
Dismiss.
Space
Activate the focused control.
Arrow Left
Move left.
Arrow Right
Move right.

Demos

Basic

Open Menu puts a short list in a dialog: Calendar, Search Emoji, and Calculator, plus a field that filters them. There are no icons and no shortcut hints. An empty state replaces the rows when nothing matches. Use the dialog when the menu should cover the page, and keep the inline list, like the one at the top of this page, when it should stay put.

Preview width

Shortcuts

Profile, Billing, and Settings, each with an icon and a shortcut hint at the end of the row. The hint is only a label, and nothing here listens for those keys. Show a shortcut when the action is also bound somewhere else, and attach that binding yourself. The dialog still opens from a button, the same way the basic menu does.

Preview width

Groups

Suggestions and Settings, split by a separator, with an icon on every row and shortcut hints only on the settings rows. Each item carries a group, and the collection builds the headings from that, so you are not hand-writing two lists. Use groups once commands fall into more than one kind. A single list is easier to scan only while it is short.

Preview width

Scrollable

Navigation, Actions, View, Account, and Tools, enough rows that the dialog has to scroll. The list already overflows on its own, so a second scroll container would fight it. Filtering still removes what does not match, which matters more at this length. Keep the headings, because a long run of unlabeled icons is harder to scan than the field is to type into.

Preview width

Palette

Command-K or Control-K toggles the dialog from anywhere on the page, and the Search button does the same for a pointer. Pages and Actions are grouped, a few rows show shortcut hints, and the footer names the arrow keys, Enter, and Escape. Picking an item writes its name under the button and closes the dialog. The value stays empty so choosing that same item again still runs.

Preview width

Rtl

The inline menu from the top of the page, with dir set to rtl on the command and on the input. Headings, labels, the placeholder, and the empty state are Arabic, and the disabled calculator is still disabled. Shortcut hints sit at the inline end of the row. Use this to check the filter and the separator when the line runs right to left.

Preview width

FAQ

How do I open the Command palette with Cmd+K in React?

Listen for the key yourself: on keydown, when the key is k and metaKey or ctrlKey is pressed, toggle the open state you pass to CommandDialog. The Palette demo has the whole handler, plus a "Search…" button for touch screens.

How do I run an action when a Command item is selected?

Pass onSelect to each CommandItem. Close the dialog in the same handler.

The Palette demo shows the selection on the page.

Should I use a Command or a Combobox?

Use a Command to run an action or jump somewhere, like a command palette or a searchable action menu. Use a Combobox when the choice is a value that stays in a form field.

Why doesn't pressing a Command shortcut do anything?

CommandShortcut is only a label at the end of an item: it shows the keys but doesn't bind them. Listen for those keys yourself, the same way the palette listens for Cmd+K.

How do I show a message when no Command results match?

Put a CommandEmpty with the text in the list: it only shows when the search leaves nothing.

How do I group Command items under headings?

Wrap related items in a CommandGroup with a heading, and put a CommandSeparator between groups, as in the Groups demo. Group by task, like Pages and Actions, rather than by where things live.

How do people use the Command with the keyboard?

The arrow keys move through the items, Enter runs the highlighted one, and typing filters the list. In CommandDialog, Escape closes the palette and focus goes back to where it was.

API Reference

Command

data-slot="command"

PropType
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandDialog

PropType
open?boolean

Whether the dialog is currently open.

defaultOpen?boolean

Whether the dialog is initially open. To render a controlled dialog, use the open prop instead.

Default
false
onOpenChange?(open: boolean, eventDetails: DialogRoot.ChangeEventDetails) → void

Event handler called when the dialog is opened or closed.

Type
(open: boolean, eventDetails: DialogRoot.ChangeEventDetails) → void
Parameters

open – boolean

eventDetails – DialogRoot.ChangeEventDetails

Returns
void
actionsRef?React.RefObject<DialogRoot.Actions | null>

A ref to imperative actions. - unmount: Ends the closing phase of the dialog after an externally controlled closing animation finishes. Call preventUnmountOnClose() in onOpenChange first, otherwise the dialog completes closing on its own. Whether it leaves the DOM is decided by keepMounted on the portal. - close: Closes the dialog imperatively when called.

Type
React.RefObject<DialogRoot.Actions | null>
defaultTriggerId?string | null

ID of the trigger that the dialog is associated with. This is useful in conjunction with the defaultOpen prop to create an initially open dialog.

Type
string | null
description?string

The dialog's description, for screen readers.

Default
"Search for a command to run..."
disablePointerDismissal?boolean

Whether to prevent the dialog from closing on outside presses. For non-modal dialogs, this also prevents the dialog from closing when focus moves outside of it.

Default
false
handle?DialogHandle<Payload>

A handle to associate the dialog with a trigger. If specified, allows external triggers to control the dialog's open state. Can be created with the Dialog.createHandle() method.

Type
DialogHandle<Payload>
modal?boolean | "trap-focus"

Determines if the dialog enters a modal state when open. - true: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled. - false: user interaction with the rest of the document is allowed. - trap-focus: focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled. When modal is true or trap-focus, render <Dialog.Close> inside <Dialog.Popup> so touch screen readers can escape the popup.

Type
boolean | "trap-focus"
Default
true
onOpenChangeComplete?(open: boolean) → void

Event handler called after any animations complete when the dialog is opened or closed.

Parameters

open – boolean

Returns
void
showCloseButton?boolean

Shows the close button in the corner.

Default
false
title?string

The dialog's title, for screen readers.

Default
"Command Palette"
triggerId?string | null

ID of the trigger that the dialog is associated with. This is useful in conjunction with the open prop to create a controlled dialog. There's no need to specify this prop when the dialog is uncontrolled (that is, when the open prop is not set).

Type
string | null
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandInput

<div> data-slot="command-input"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandList

data-slot="command-list"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandEmpty

data-slot="command-empty"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandGroup

data-slot="command-group"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandSeparator

data-slot="command-separator"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandItem

data-slot="command-item"

PropType
asChild?boolean

Use the provided child element as the default rendered element, combining their props and behavior.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CommandShortcut

<span> data-slot="command-shortcut"

PropType
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

With other components

  • Free

    Dialog

    Overlays

    Palette in a modal

  • Free

    Button

    Buttons

    Opens the palette

  • Free

    Kbd

    Typography

    Shortcut on the row

  • Free

    Popover

    Overlays

    Command as a picker

  • Free

    Combobox

    Selection

    Type to pick one

  • Free

    Separator

    Layout

    Split the groups

  • Free

    Shortcuts in a menu

  • Free

    Right-click the same actions

  • Free

    Menubar

    Menus

    App menu shortcuts

  • Free

    Input

    Inputs

    Search without a list

  • Free

    Empty

    Feedback

    No matches, full page

  • Free

    Listbox

    Selection

    The list stays on the page