sdxc

Type to search, or start from one of these:

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/ui
import "@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.

  • Command
  • Command.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, marked data-command-input for a paired filter mixin to read.
  • Command.ListRenders the panel's scrollable option region: a <div> carrying the listbox role, 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 the option role, its value mirrored onto data-value for 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 a data-command-empty marker 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.

PropTypeDescription
childrenRemixNodeThe panel's compound parts: Command.Input, Command.List, Command.Empty.

Also accepts everything in TagProps<"div">.

Command.Input

Command.List

PropTypeDescription
childrenRemixNodeThe Command.Item rows (and, once nothing matches, Command.Empty) to scroll through.

Also accepts everything in TagProps<"div">.

Command.Item

PropTypeDescription
valuestringPlain-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?RemixNodeThe 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">.