Command
Command palette with fuzzy search, groups, keyboard shortcuts, and empty state.
Examples
Command dialog
The same palette in a modal — the most common ⌘K pattern.
Press ⌘J
Command Palette
Search for a command to run...
import {
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@codefast/ui/command";
import { Calculator, Calendar, CreditCard, Settings, Smile, User } from "lucide-react";
import * as React from "react";
export function CommandDialogDemo() {
const [open, setOpen] = React.useState(false);
React.useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === "j" && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
setOpen((open) => !open);
}
};
document.addEventListener("keydown", down);
return () => document.removeEventListener("keydown", down);
}, []);
return (
<>
<p className="text-sm text-muted-foreground">
Press{" "}
<kbd className="pointer-events-none inline-flex h-5 items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100 select-none">
<span className="text-xs">⌘</span>J
</kbd>
</p>
<CommandDialog open={open} onOpenChange={setOpen}>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>
<Calendar />
<span>Calendar</span>
</CommandItem>
<CommandItem>
<Smile />
<span>Search Emoji</span>
</CommandItem>
<CommandItem>
<Calculator />
<span>Calculator</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>
<User />
<span>Profile</span>
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCard />
<span>Billing</span>
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
<CommandItem>
<Settings />
<span>Settings</span>
<CommandShortcut>⌘S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>
</>
);
}
Basic
A simple command menu in a dialog.
Command Palette
Search for a command to run...
import { Button } from "@codefast/ui/button";
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@codefast/ui/command";
import * as React from "react";
export function CommandBasic() {
const [open, setOpen] = React.useState(false);
return (
<div className="flex flex-col gap-4">
<Button onClick={() => setOpen(true)} variant="outline" className="w-fit">
Open Menu
</Button>
<CommandDialog open={open} onOpenChange={setOpen}>
<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</CommandDialog>
</div>
);
}
Groups
A command menu with groups, icons and separators.
Command Palette
Search for a command to run...
import { Button } from "@codefast/ui/button";
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@codefast/ui/command";
import { CalculatorIcon, CalendarIcon, CreditCardIcon, SettingsIcon, SmileIcon, UserIcon } from "lucide-react";
import * as React from "react";
export function CommandWithGroups() {
const [open, setOpen] = React.useState(false);
return (
<div className="flex flex-col gap-4">
<Button onClick={() => setOpen(true)} variant="outline" className="w-fit">
Open Menu
</Button>
<CommandDialog open={open} onOpenChange={setOpen}>
<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>
<CalendarIcon />
<span>Calendar</span>
</CommandItem>
<CommandItem>
<SmileIcon />
<span>Search Emoji</span>
</CommandItem>
<CommandItem>
<CalculatorIcon />
<span>Calculator</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>
<UserIcon />
<span>Profile</span>
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCardIcon />
<span>Billing</span>
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
<CommandItem>
<SettingsIcon />
<span>Settings</span>
<CommandShortcut>⌘S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</CommandDialog>
</div>
);
}
RTL
Right-to-left layout support for languages such as Arabic and Hebrew.
Translations are AI-generated for demonstration and may be imperfect.
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@codefast/ui/command";
import { Calculator, Calendar, CreditCard, Settings, Smile, User } from "lucide-react";
import type { Translations } from "#/features/components-catalog/components/detail/language";
import { useTranslation } from "#/features/components-catalog/components/detail/language-context";
const translations: Translations = {
en: {
dir: "ltr",
values: {
placeholder: "Type a command or search...",
empty: "No results found.",
suggestions: "Suggestions",
calendar: "Calendar",
searchEmoji: "Search Emoji",
calculator: "Calculator",
settings: "Settings",
profile: "Profile",
billing: "Billing",
},
},
ar: {
dir: "rtl",
values: {
placeholder: "اكتب أمرًا أو ابحث...",
empty: "لم يتم العثور على نتائج.",
suggestions: "اقتراحات",
calendar: "التقويم",
searchEmoji: "البحث عن الرموز التعبيرية",
calculator: "الآلة الحاسبة",
settings: "الإعدادات",
profile: "الملف الشخصي",
billing: "الفوترة",
},
},
he: {
dir: "rtl",
values: {
placeholder: "הקלד פקודה או חפש...",
empty: "לא נמצאו תוצאות.",
suggestions: "הצעות",
calendar: "לוח שנה",
searchEmoji: "חפש אמוג'י",
calculator: "מחשבון",
settings: "הגדרות",
profile: "פרופיל",
billing: "חיוב",
},
},
};
export function CommandRtl() {
const { dir, t } = useTranslation(translations, "ar");
return (
<Command className="max-w-sm rounded-lg border" dir={dir}>
<CommandInput placeholder={t.placeholder} dir={dir} />
<CommandList>
<CommandEmpty>{t.empty}</CommandEmpty>
<CommandGroup heading={t.suggestions}>
<CommandItem>
<Calendar />
<span>{t.calendar}</span>
</CommandItem>
<CommandItem>
<Smile />
<span>{t.searchEmoji}</span>
</CommandItem>
<CommandItem disabled>
<Calculator />
<span>{t.calculator}</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading={t.settings}>
<CommandItem>
<User />
<span>{t.profile}</span>
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCard />
<span>{t.billing}</span>
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
<CommandItem>
<Settings />
<span>{t.settings}</span>
<CommandShortcut>⌘S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
);
}
Scrollable
Scrollable command menu with multiple items.
Command Palette
Search for a command to run...
import { Button } from "@codefast/ui/button";
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@codefast/ui/command";
import {
BellIcon,
CalculatorIcon,
CalendarIcon,
ClipboardPasteIcon,
CodeIcon,
CopyIcon,
CreditCardIcon,
FileTextIcon,
FolderIcon,
FolderPlusIcon,
HelpCircleIcon,
HomeIcon,
ImageIcon,
InboxIcon,
LayoutGridIcon,
ListIcon,
PlusIcon,
ScissorsIcon,
SettingsIcon,
TrashIcon,
UserIcon,
ZoomInIcon,
ZoomOutIcon,
} from "lucide-react";
import * as React from "react";
export function CommandManyItems() {
const [open, setOpen] = React.useState(false);
return (
<div className="flex flex-col gap-4">
<Button onClick={() => setOpen(true)} variant="outline" className="w-fit">
Open Menu
</Button>
<CommandDialog open={open} onOpenChange={setOpen}>
<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Navigation">
<CommandItem>
<HomeIcon />
<span>Home</span>
<CommandShortcut>⌘H</CommandShortcut>
</CommandItem>
<CommandItem>
<InboxIcon />
<span>Inbox</span>
<CommandShortcut>⌘I</CommandShortcut>
</CommandItem>
<CommandItem>
<FileTextIcon />
<span>Documents</span>
<CommandShortcut>⌘D</CommandShortcut>
</CommandItem>
<CommandItem>
<FolderIcon />
<span>Folders</span>
<CommandShortcut>⌘F</CommandShortcut>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Actions">
<CommandItem>
<PlusIcon />
<span>New File</span>
<CommandShortcut>⌘N</CommandShortcut>
</CommandItem>
<CommandItem>
<FolderPlusIcon />
<span>New Folder</span>
<CommandShortcut>⇧⌘N</CommandShortcut>
</CommandItem>
<CommandItem>
<CopyIcon />
<span>Copy</span>
<CommandShortcut>⌘C</CommandShortcut>
</CommandItem>
<CommandItem>
<ScissorsIcon />
<span>Cut</span>
<CommandShortcut>⌘X</CommandShortcut>
</CommandItem>
<CommandItem>
<ClipboardPasteIcon />
<span>Paste</span>
<CommandShortcut>⌘V</CommandShortcut>
</CommandItem>
<CommandItem>
<TrashIcon />
<span>Delete</span>
<CommandShortcut>⌫</CommandShortcut>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="View">
<CommandItem>
<LayoutGridIcon />
<span>Grid View</span>
</CommandItem>
<CommandItem>
<ListIcon />
<span>List View</span>
</CommandItem>
<CommandItem>
<ZoomInIcon />
<span>Zoom In</span>
<CommandShortcut>⌘+</CommandShortcut>
</CommandItem>
<CommandItem>
<ZoomOutIcon />
<span>Zoom Out</span>
<CommandShortcut>⌘-</CommandShortcut>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Account">
<CommandItem>
<UserIcon />
<span>Profile</span>
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCardIcon />
<span>Billing</span>
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
<CommandItem>
<SettingsIcon />
<span>Settings</span>
<CommandShortcut>⌘S</CommandShortcut>
</CommandItem>
<CommandItem>
<BellIcon />
<span>Notifications</span>
</CommandItem>
<CommandItem>
<HelpCircleIcon />
<span>Help & Support</span>
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Tools">
<CommandItem>
<CalculatorIcon />
<span>Calculator</span>
</CommandItem>
<CommandItem>
<CalendarIcon />
<span>Calendar</span>
</CommandItem>
<CommandItem>
<ImageIcon />
<span>Image Editor</span>
</CommandItem>
<CommandItem>
<CodeIcon />
<span>Code Editor</span>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</CommandDialog>
</div>
);
}
Shortcuts
Command menu for search and quick actions.
Command Palette
Search for a command to run...
import { Button } from "@codefast/ui/button";
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandShortcut,
} from "@codefast/ui/command";
import { CreditCardIcon, SettingsIcon, UserIcon } from "lucide-react";
import * as React from "react";
export function CommandWithShortcuts() {
const [open, setOpen] = React.useState(false);
return (
<div className="flex flex-col gap-4">
<Button onClick={() => setOpen(true)} variant="outline" className="w-fit">
Open Menu
</Button>
<CommandDialog open={open} onOpenChange={setOpen}>
<Command>
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Settings">
<CommandItem>
<UserIcon />
<span>Profile</span>
<CommandShortcut>⌘P</CommandShortcut>
</CommandItem>
<CommandItem>
<CreditCardIcon />
<span>Billing</span>
<CommandShortcut>⌘B</CommandShortcut>
</CommandItem>
<CommandItem>
<SettingsIcon />
<span>Settings</span>
<CommandShortcut>⌘S</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</CommandDialog>
</div>
);
}
Anatomy
How the parts nest — every slot the component exposes, in composition order.
Features
- Built on cmdk — filters items by the input as you type; set shouldFilter={false} to filter server-side instead.
- CommandDialog wraps the palette in a Dialog with a screen-reader-only title/description by default, ready for the classic ⌘K pattern.
- CommandInput renders inside an InputGroup with a search icon addon — the same primitive Input Group and Input Search use.
API reference
Props for each part of the component. All native element props are also forwarded.
Command
Built on cmdk. Filters items by the input as you type.
valuestringThe controlled highlighted item.
defaultValuestringThe highlighted item when initially rendered (uncontrolled).
onValueChange(value: string) => voidCalled when the highlighted item changes.
shouldFilterbooleanTurn off built-in filtering to filter server-side.
Default
true
CommandItem
onSelect(value: string) => voidRuns when the item is chosen by click or Enter.
disabledbooleanSkip the item during filtering and keyboard nav.
Default
false
CommandDialog
Command inside a Dialog.
openbooleanThe controlled visibility of the modal palette.
defaultOpenbooleanThe visibility when initially rendered (uncontrolled).
onOpenChange(open: boolean) => voidCalled when the modal palette’s visibility changes.
Accessibility
Built to be keyboard-navigable and screen-reader friendly out of the box.
| Key | Function |
|---|---|
| Arrow+Down | Highlights the next item. |
| Arrow+Up | Highlights the previous item. |
| Enter | Runs the highlighted item. |
| Esc | Closes the command dialog. |
- The input is a combobox controlling a listbox; highlighting is announced.
- Always provide a CommandEmpty so an empty search is communicated.
- Bind ⌘K / Ctrl+K to open the dialog in real apps — shown here as a hint only.
Guidelines
Conventions that keep usage consistent across an app.
Do
- Group commands and add a short heading per group.
- Show shortcuts with CommandShortcut so power users learn them.
Don’t
- Don’t hide the only path to an action behind the palette.
- Don’t list hundreds of flat items without groups or search hints.
Explore further
Ready to integrate?
Follow the Getting Started guide to install @codefast/ui, or browse the full component gallery.