Command
A bordered panel for searching and choosing among a list of actions.
No command matches that.
Arrow keys move the active row; Enter runs it.
View code
let model = new FilterModel();
let ran: string | null = null;
<div mix={[vstack({ gap: 2, align: "stretch" }), is("100%"), maxIs("26rem")]}>
<Command
aria-label="Workspace commands"
mix={[commandFilter(model), commandKeys(model)]}
>
<Command.Input
type="search"
aria-label="Workspace commands"
placeholder="Type a command or search…"
/>
<Command.List>
{ACTIONS.map((action) => (
<Command.Item key={action.id} id={`preview-command-${action.id}`} value={action.label}>
<button
type="button"
mix={[
hstack({ gap: 3, align: "center" }),
is("100%"),
on<HTMLButtonElement, "click">("click", () => {
ran = action.label;
void handle.update();
}),
]}
>
{actionIcon(action.icon)}
<span mix={[is("100%"), textAlign("start"), text("sm")]}>{action.label}</span>
{action.hint ? <Keyboard>{action.hint}</Keyboard> : null}
</button>
</Command.Item>
))}
</Command.List>
<Command.Empty>No command matches that.</Command.Empty>
</Command>
<p mix={[text("sm"), fg("neutral")]}>
{ran === null ? "Arrow keys move the active row; Enter runs it." : `Ran: ${ran}`}
</p>
</div>Installation
An ordinary dependency: install it, import the theme once, and import the component where it is used.
npm add @sdxc/uiimport "@sdxc/ui/theme.css";Usage
import { Command } from "@sdxc/ui";Renders the panel's root host: a bordered, rounded, elevated <div>
stacking its compound parts in a column, clipping Command.List's
scrolled content to the panel's own rounded corners.
Composition
The parts the component publishes, each a static property of the host.
CommandCommand.InputRenders the panel's query row: a<div>bordered along its block-end edge wrapping a native<input>sized to the row's full padding and height, markeddata-command-inputfor a paired filter mixin to read.Command.ListRenders the panel's scrollable option region: a<div>carrying thelistboxrole, capped at a fixed block size, its small inline padding leaving room for a selected Command.Item's own rounded corners.Command.ItemRenders a single row: a<div>carrying theoptionrole, itsvaluemirrored ontodata-valuefor a paired filter behavior to read.Command.EmptyRenders the panel's no-match message: a centered, muted passage of small text filling Command.List's content area, carrying adata-command-emptymarker a paired filter behavior reads to toggle it.
Props
Read from the component's own types, so every prop, every default and every allowed value is listed.
| Prop | Type | Description |
|---|---|---|
children | RemixNode | The panel's compound parts: Command.Input, Command.List, Command.Empty. |
Also accepts everything in TagProps<"div">.
Command.Input
Command.List
| Prop | Type | Description |
|---|---|---|
children | RemixNode | The Command.Item rows (and, once nothing matches, Command.Empty) to scroll through. |
Also accepts everything in TagProps<"div">.
Command.Item
| Prop | Type | Description |
|---|---|---|
value | string | Plain-text value identifying this row's content. A paired filter behavior matches typed text against this value directly, so it stays required even when the visible content is already plain text. |
children? | RemixNode | The row's visible content: a label, and optionally a leading icon or trailing hint. |
Also accepts everything in TagProps<"div">.
Command.Empty
Also accepts everything in TagProps<"div">.