Command
A searchable list of pages and actions, inline or as a command palette in a dialog.
@zenoxai/ui/components/command Markdown<Command className="max-w-sm rounded-lg border border-border">
<CommandInput placeholder="Search pages and actions" />
<CommandList>
<CommandEmpty>No results.</CommandEmpty>
<CommandGroup heading="Pages">
<CommandItem>
<BellIcon />
Alerts
</CommandItem>
<CommandItem>
<ServerIcon />
Assets
</CommandItem>
<CommandItem>
<ShieldAlertIcon />
Vulnerabilities
</CommandItem>
<CommandItem>
<FileTextIcon />
Reports
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Actions">
<CommandItem>
<PlusIcon />
New investigation
<CommandShortcut>⌘I</CommandShortcut>
</CommandItem>
<CommandItem>
<FileTextIcon />
Export weekly report
<CommandShortcut>⌘E</CommandShortcut>
</CommandItem>
</CommandGroup>
</CommandList>
</Command>Usage
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@zenoxai/ui/components/command"
<Command>
<CommandInput placeholder="Search pages and actions" />
<CommandList>
<CommandEmpty>No results.</CommandEmpty>
<CommandGroup heading="Pages">
<CommandItem onSelect={() => navigate("/alerts")}>Alerts</CommandItem>
<CommandItem onSelect={() => navigate("/assets")}>Assets</CommandItem>
</CommandGroup>
</CommandList>
</Command>
Command is built on cmdk. It filters and ranks its items as the user
types, moves the highlight with the arrow keys and runs onSelect on Enter or click. Use it for
long lists of commands or destinations that people find faster by typing than by scanning: a
command palette, a “go to” list, a picker with dozens of entries.
- For a few actions behind a button, use a Dropdown Menu.
- For a value in a form, use a Combobox: it has the field semantics a form needs.
Items match on their text. When the text is not what people type, or two items share it, pass
a value (and keywords for synonyms). CommandEmpty shows when nothing matches.
CommandShortcut only displays a shortcut; bind the key yourself.
When it mounts, Command scrolls its first item into view, and that scrolls the page too. Place
an inline Command where it is visible on load, or inside an overlay that mounts it on open, as
in the examples below.
Examples
Command palette
CommandDialog puts a Command in a Dialog, placed in the upper third
of the screen. It has no trigger part: control open and open it from a button, a keyboard
shortcut, or both. Close it in each item’s onSelect. title and description label the
dialog for screen readers and are not shown.
function CommandInDialog() {
const [open, setOpen] = React.useState(false)
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
<SearchIcon data-icon="inline-start" />
Search
</Button>
<CommandDialog
open={open}
onOpenChange={setOpen}
title="Command palette"
description="Search for a page or an action"
>
<Command>
{/* Each item's onSelect navigates or runs its action, then closes. */}
<CommandInput placeholder="Type a command or search" />
<CommandList>
<CommandEmpty>No results.</CommandEmpty>
<CommandGroup heading="Pages">
<CommandItem onSelect={() => setOpen(false)}>
<BellIcon />
Alerts
</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>
<ServerIcon />
Assets
</CommandItem>
<CommandItem onSelect={() => setOpen(false)}>
<FileTextIcon />
Reports
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Actions">
<CommandItem onSelect={() => setOpen(false)}>
<PlusIcon />
New investigation
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</CommandDialog>
</>
)
}In a popover
For a picker attached to a button, such as the assignee of an alert, put a Command in a
Popover with p-0 on the content. Set data-checked on the current
item to show a check mark at its end, and close the popover in onSelect. When the value
belongs to a form field, use a Combobox instead.
function CommandInPopover() {
const [open, setOpen] = React.useState(false)
const [assignee, setAssignee] = React.useState("Marina Santos")
const analysts = ["Marina Santos", "Jordan Lee", "Ada Okafor", "Thanh Nguyen"]
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger render={<Button variant="outline" />}>
<UserIcon data-icon="inline-start" />
{assignee}
</PopoverTrigger>
<PopoverContent align="start" className="w-60 p-0">
<Command>
<CommandInput placeholder="Assign to" />
<CommandList>
<CommandEmpty>No analyst found.</CommandEmpty>
<CommandGroup heading="Analysts">
{analysts.map((name) => (
<CommandItem
key={name}
data-checked={assignee === name}
onSelect={() => {
setAssignee(name)
setOpen(false)
}}
>
{name}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
)
}Accessibility
- The input is a combobox that controls the list. Arrow keys move the highlight, Enter selects and the highlighted item is announced; focus stays in the input.
- Give
CommandDialogatitlethat names its purpose (“Command palette”, “Go to page”). It is the dialog’s accessible name. - Group headings are announced as the names of their groups.
API reference
Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.
Command
Command is a searchable list of actions, built on cmdk: type to filter, arrows to move, Enter to run. Use it for a command palette (CommandDialog) or an action picker in a popover. To pick a form value from a long list, use Combobox.
No props of its own. Accepts the props of the element it renders.
CommandDialog
CommandDialog opens a Command in a modal dialog near the top of the screen: the command palette. Control it with `open` and `onOpenChange`, and bind the shortcut that opens it yourself.
| Prop | Type | Default |
|---|---|---|
actionsRef | RefObject<DialogRootActions | 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. | - |
defaultOpen | booleanWhether the dialog is initially open. | false |
defaultTriggerId | string | nullID of the trigger that the dialog is associated with. This is useful in conjunction with the `defaultOpen` prop to create an initially open dialog. | - |
description | stringAccessible description, visually hidden; pass a translated one. | Search for a command to run |
disablePointerDismissal | booleanWhether 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. | false |
handle | DialogHandle<unknown>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. | - |
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. | true |
onOpenChange | ((open: boolean, eventDetails: DialogRootChangeEventDetails) => void)Event handler called when the dialog is opened or closed. | - |
onOpenChangeComplete | ((open: boolean) => void)Event handler called after any animations complete when the dialog is opened or closed. | - |
open | booleanWhether the dialog is currently open. | - |
showCloseButton | booleanShows the X button at the top-right corner; Escape closes it anyway. | false |
title | stringAccessible name of the dialog, visually hidden; pass a translated one. | Command palette |
triggerId | string | nullID 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). | - |
CommandInput
CommandInput is the search field that filters the items.
No props of its own. Accepts the props of the element it renders.
CommandList
No props of its own. Accepts the props of the element it renders.
CommandEmpty
CommandEmpty is the message shown when no item matches the query.
No props of its own. Accepts the props of the element it renders.
CommandGroup
No props of its own. Accepts the props of the element it renders.
CommandItem
No props of its own. Accepts the props of the element it renders.
CommandShortcut
CommandShortcut is the key hint at the right edge of an item. It is display text only: bind the keys yourself.
No props of its own. Accepts the props of the element it renders.
CommandSeparator
No props of its own. Accepts the props of the element it renders.