Components
Command
A fast, composable command palette for searching and executing actions. Use it as a modal dialog or embedded inline in a page.
example.tsx
Import
tsx
import {
AppCommand,
AppCommandDialog,
AppCommandInput,
AppCommandList,
AppCommandEmpty,
AppCommandGroup,
AppCommandItem,
AppCommandShortcut,
AppCommandSeparator,
} from "@/components/primitives/AppCommand"Inline
Use AppCommand directly (without the dialog wrapper) to embed the palette inline on a page — for example inside a popover or a sidebar.
tsx
<AppCommand>
<AppCommandInput placeholder="Search..." />
<AppCommandList>
<AppCommandEmpty>No results found.</AppCommandEmpty>
<AppCommandGroup heading="Pages">
<AppCommandItem>Dashboard</AppCommandItem>
<AppCommandItem>Settings</AppCommandItem>
</AppCommandGroup>
</AppCommandList>
</AppCommand>Keyboard trigger
The standard pattern is to open the command dialog with ⌘K (or Ctrl+K on Windows). Add a useEffect to wire this up globally.
tsx
const [open, setOpen] = useState(false)
useEffect(() => {
const down = (e: KeyboardEvent) => {
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
e.preventDefault()
setOpen((open) => !open)
}
}
document.addEventListener("keydown", down)
return () => document.removeEventListener("keydown", down)
}, [])
<AppCommandDialog open={open} onOpenChange={setOpen}>
{/* ... */}
</AppCommandDialog>Shortcuts
Use AppCommandShortcut to display a keyboard shortcut hint alongside a command item.
tsx
<AppCommandItem>
Profile
<AppCommandShortcut>⌘P</AppCommandShortcut>
</AppCommandItem>API Reference
AppCommandDialog and its sub-components extend the underlying Radix UI Dialog and cmdk primitives.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state of the dialog. |
| onOpenChange | (open: boolean) => void | — | Callback fired when the open state changes. |
| filter | (value: string, search: string) => number | — | Custom filter function for AppCommand. Return a score between 0 and 1. |
| shouldFilter | boolean | true | Set to false to disable built-in filtering and handle it yourself. |
| className | string | — | Additional Tailwind classes merged via cn(). Prefer the wrapper pattern for reusable overrides. |
Source
src/components/primitives/AppCommand.tsx
"use client"
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@/components/ui/command"
function AppCommand(props: React.ComponentProps<typeof Command>) {
return <Command {...props} />
}
function AppCommandDialog(props: React.ComponentProps<typeof CommandDialog>) {
return <CommandDialog {...props} />
}
function AppCommandInput(props: React.ComponentProps<typeof CommandInput>) {
return <CommandInput {...props} />
}
function AppCommandList(props: React.ComponentProps<typeof CommandList>) {
return <CommandList {...props} />
}
function AppCommandEmpty(props: React.ComponentProps<typeof CommandEmpty>) {
return <CommandEmpty {...props} />
}
function AppCommandGroup(props: React.ComponentProps<typeof CommandGroup>) {
return <CommandGroup {...props} />
}
function AppCommandItem(props: React.ComponentProps<typeof CommandItem>) {
return <CommandItem {...props} />
}
function AppCommandShortcut(props: React.HTMLAttributes<HTMLSpanElement>) {
return <CommandShortcut {...props} />
}
function AppCommandSeparator(props: React.ComponentProps<typeof CommandSeparator>) {
return <CommandSeparator {...props} />
}
export {
AppCommand,
AppCommandDialog,
AppCommandInput,
AppCommandList,
AppCommandEmpty,
AppCommandGroup,
AppCommandItem,
AppCommandShortcut,
AppCommandSeparator,
}