Skip to Content
Columbus

Command

A command palette component built with Dialog and Autocomplete for searching and executing commands.

Installation

pnpm dlx shadcn@latest add @columbus/command

Usage

import { Button } from "@/components/ui/button";
import {
  Command,
  CommandDialog,
  CommandDialogPopup,
  CommandDialogTrigger,
  CommandEmpty,
  CommandInput,
  CommandItem,
  CommandList,
  CommandPanel,
} from "@/components/ui/command";

const items = [
  { label: "Linear", value: "linear" },
  { label: "Figma", value: "figma" },
];

<CommandDialog>
  <CommandDialogTrigger render={<Button variant="outline" />}>
    Open command palette
  </CommandDialogTrigger>
  <CommandDialogPopup aria-label="Command palette">
    <Command items={items}>
      <CommandInput aria-label="Search" placeholder="Search…" />
      <CommandPanel>
        <CommandEmpty>No results found.</CommandEmpty>
        <CommandList>
          {(item) => (
            <CommandItem key={item.value} value={item.value}>
              {item.label}
            </CommandItem>
          )}
        </CommandList>
      </CommandPanel>
    </Command>
  </CommandDialogPopup>
</CommandDialog>;

The first match is always highlighted, so pressing Enter runs it. Handle an item with its onClick, which also fires on Enter. To close the dialog afterwards, control it with open and onOpenChange.

Give CommandDialogPopup an aria-label, since the dialog has no visible title. CommandList takes a function, so render command in a Client Component.

Keyboard shortcut

The demo above opens with ⌘J / Ctrl+J. Listen for the shortcut and toggle the controlled open state:

const [open, setOpen] = useState(false);

useEffect(() => {
  function onKeyDown(event: KeyboardEvent) {
    if (event.key === "j" && (event.metaKey || event.ctrlKey)) {
      event.preventDefault();
      setOpen((open) => !open);
    }
  }
  document.addEventListener("keydown", onKeyDown);
  return () => document.removeEventListener("keydown", onKeyDown);
}, []);

Without a dialog

Command also works on its own, for example in a page or a popover. The list is always shown.

CommandInput focuses itself when it mounts. Pass autoFocus={false} when the command is part of a page.

API reference

Command is Base UI Autocomplete with command palette defaults, and accepts all its props. CommandDialog, CommandDialogTrigger, and CommandDialogPopup are Base UI Dialog parts.

ComponentDescription
CommandInputLarge search input with a search icon.
CommandListScrollable list of results.
CommandItemA result.
CommandGroup, CommandGroupLabelA labelled group of results. Render items with CommandCollection.
CommandSeparatorA divider between groups.
CommandEmptyShown when nothing matches.
CommandShortcutA shortcut hint at the end of an item.
CommandPanelThe bordered panel around the results inside a dialog.
CommandFooterA bar below the results for hints.

Command

Prop

Type

Command also sets inline, so the list renders in place instead of in a popup.

CommandDialogPopup

Renders the portal, backdrop, and viewport for you.

Prop

Type

CommandInput

Accepts every AutocompleteInput prop. It defaults to size="lg", a search icon startAddon, and autoFocus.

On this page