Command
commandSearches and executes grouped commands through a keyboard-first palette.
Usage
Basic usage
Command is in controlled mode: hold open with useState, and the button triggers to open. groups provides grouping commands, and the input box is filtered across groups in real time (try entering "Order", "dd" and "Topic").
const [open, setOpen] = useState(false);
const groups = [
{
heading: "Quick jump",
items: [
{ value: "go-dashboard", label: "Dashboard", description: "Overview of today's data",
keywords: "dashboard Home", icon: <LayoutDashboard /> },
{ value: "go-orders", label: "Order Management", keywords: "order Order dd",
icon: <ShoppingCart /> },
],
},
{
heading: "Operation",
items: [
{ value: "new-order", label: "New Order", icon: <Plus />, shortcut: "⌘N" },
{ value: "import", label: "Import data", description: "Upload CSV / Excel",
icon: <Upload /> },
],
},
];
<Button variant="outline" onClick={() => setOpen(true)}>Open the command panel</Button>
<Command open={open} onOpenChange={setOpen} groups={groups} />Built-in ⌘K shortcut keys
After shortcut is turned on, the component has built-in ⌘K / Ctrl+K global monitoring switch, no need to bind it yourself.
<Button variant="outline" onClick={() => setOpen(true)}>
Open the command panel (or ⌘K)
</Button>
<Command open={open} onOpenChange={setOpen} groups={groups} shortcut />Keep open after selection
closeOnSelect={false} The panel does not close after executing the command, which is suitable for scenarios with multiple consecutive operations.
<Command
open={open}
onOpenChange={setOpen}
groups={groups}
closeOnSelect={false}
/>When to use
Use Command for a global Command/Ctrl+K palette that brings cross-page navigation, actions, and theme switching into one searchable, grouped, keyboard-navigable surface. Use Toolbar for a persistent row of controls or ContextMenu for actions opened at a pointer location. Command is a modal, data-driven search entry point.
Import
import { Command, useCommandShortcut } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| open* | boolean | — | Controlled open state. |
| groups* | CommandGroupData[] | — | Command groups, each with an optional heading. |
| placeholder | string | "\u8f93\u5165\u547d\u4ee4\u6216\u641c\u7d22\u2026" | Search-field placeholder. The built-in Chinese copy means “Type a command or search…”. |
| filter | (item: CommandItemData, query: string) => boolean | Substring match | Custom predicate; return true to retain an item. The default case-insensitively searches keywords, string label, and value. |
| closeOnSelect | boolean | true | Whether executing an item closes the palette. |
| shortcut | boolean | false | Whether to install the global Command/Ctrl+K open-state shortcut. |
| className | string | — | Additional class name. |
| aria-label | string | "\u547d\u4ee4\u9762\u677f" | Accessible label. The built-in Chinese copy means “Command palette.” |
Events
| Event | Type | Description |
|---|---|---|
| onOpenChange* | (open: boolean) => void | Called when the palette requests an open-state change. |
| onSelectItem | (value: string) => void | Called after an item's own onSelect, with its value. |
| onQueryChange | (query: string) => void | Called on query changes, including the reset each time the palette opens. Use it with filter={() => true} when the consumer owns sorting, grouping, and filtering. |
Slots
| Slot | Type | Description |
|---|---|---|
| emptyMessage | ReactNode | Empty-state content shown when no command matches. The built-in Chinese copy is "\u65e0\u5339\u914d\u7ed3\u679c", meaning “No matching results.” |
CommandGroupData: heading?: ReactNode / items: CommandItemData[].
CommandItemData
| Field | Type | Description |
|---|---|---|
| value* | string | Unique value used for callbacks, the React key, and fallback filtering. |
| label* | ReactNode | Visible title. |
| keywords | string | Additional searchable terms, especially for non-string labels. |
| description | ReactNode | Muted secondary content below the label. |
| icon | ReactNode | Leading icon. |
| shortcut | ReactNode | Trailing keyboard shortcut or marker. |
| disabled | boolean | Whether the item is unavailable. |
| onSelect | (value: string) => void | Called when Enter or a click executes the item. |
Example
const groups = [
{
heading: "Quick navigation",
items: [
{ value: "go-orders", label: "Orders", keywords: "orders", icon: <ShoppingCart />, onSelect: () => router.push("/orders") },
{ value: "new-order", label: "New order", icon: <Plus />, shortcut: "⌘N" },
],
},
];
const [open, setOpen] = useState(false);
<Command open={open} onOpenChange={setOpen} groups={groups} shortcut placeholder="Type a command or search…" />Usage guidelines
- Command is always controlled; provide both
openandonOpenChange. - A non-string
labelis not directly searchable by the default filter. Addkeywords, or the item can match only throughvalue. - Enable the built-in shortcut with
shortcut. If the surrounding application installs its own trigger, useuseCommandShortcutinstead and do not enable both.
Related
ContextMenu · Toolbar · Accordion · Collapsible · Link · AnimatedThemeToggler
Playground
const [open, setOpen] = useState(false);
<Button onClick={() => setOpen(true)}>Open the command panel</Button>
<Command
open={open}
onOpenChange={setOpen}
placeholder="Enter command or search..."
shortcut={false}
groups={[
{ heading: "Commonly used", items: [{ value: "new", label: "New file", onSelect: (v) => {} }] },
]}
/>