Command
Fast, composable command menu. Type to filter (prefix, substring or fuzzy subsequence, plus keywords); ↑ / ↓ move the highlight and Enter selects it.
Usage
Approximate web preview — the HarmonyOS rendering is the reference.
Dialog
SCommandDialog shows the palette in a centred dialog and closes after a selection.
Approximate web preview — the HarmonyOS rendering is the reference.
Long lists (data mode)
Pass items instead of slot content: the results are virtualized, so items that do not match are never built and only the matches in view are. Try "echo 42", "set 19" or "dlt".
Approximate web preview — the HarmonyOS rendering is the reference.
MANY_COMMANDS.length items · query = "…" · selected = …
API
Extracted from the @Param / @Event / @BuilderParam declarations in the library sources.
SparkCommandDataList
Virtualized result list of SCommand({ items }) (ADR D14): List + Repeat(...).virtualScroll() with two templates (item / heading). Only rows in view (plus cachedCount) exist; filtered-out items are not in entries at all. The height is explicit (sum of the row heights, capped at maxListHeight), and childrenMainSize gives every row's exact height, so scrollToIndex keeps the highlight in view without measuring frame nodes. Rows take only @Params (reused rows never register anywhere).
| Prop | Type | Default | Description |
|---|---|---|---|
entries | SparkCommandRow[] | [] | |
highlighted | string | '' | |
maxListHeight | number | 300 | |
rowsFocusable | boolean | false | rows take keyboard focus (no search field); false while an input keeps focus and drives the highlight |
| Event | Type | Default | Description |
|---|---|---|---|
onPick | (value: string) => void | () => { } | |
onHighlight | (value: string) => void | () => { } |
SCommand
shadcn-vue Command (cmdk): a searchable, keyboard-navigable list of actions.
Items are matched case-insensitively against the query (prefix, substring, then subsequence — see sparkCommandScore); groups with no matching item hide; ↑ / ↓ move the highlight, Enter selects it. Results keep their document order (they are filtered, not re-sorted).
Data mode (long lists, ADR D14): pass items instead of slot content. The command then renders its own search field and a virtualized list (List + Repeat.virtualScroll()): items that do not match the query are never built, and of the matches only the rows in view are.
Consecutive items with the same group share a heading. ↑ / ↓ in the field move the highlight (the list scrolls to it), Enter or a tap activates an item (onSelect of the item, then onItemSelect). Values must be unique. showInput: false drops the field (rows then take focus).
| Prop | Type | Default | Description |
|---|---|---|---|
shouldFilter | boolean | true | false: show every item regardless of the query (filter the data yourself via onQueryChange) |
items | SparkCommandEntryData[] | undefined | undefined | data mode: the items (virtualized list with a built-in search field); undefined = slot mode |
placeholder | ResourceStr | $r('app.string.spark_command_placeholder') | data mode: search field placeholder |
emptyText | ResourceStr | $r('app.string.spark_no_results') | data mode: text shown when nothing matches |
maxListHeight | number | 300 | data mode: max height of the result list (vp) |
showInput | boolean | true | data mode: render the search field (false: rows take focus, the developer drives the query) |
autoFocus | boolean | false | data mode: focus the field when the command appears (pointer devices; keeps the keyboard closed on touch) |
| Event | Type | Default | Description |
|---|---|---|---|
onQueryChange | (query: string) => void | () => { } | |
onItemSelect | (value: string) => void | () => { } | fired after any item is selected (with its value) |
Slots: children (trailing closure)
SCommandInput
flex h-9 items-center gap-2 border-b px-3 with a search icon and a borderless input.
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | ResourceStr | $r('app.string.spark_command_placeholder') | |
autoFocus | boolean | false | focus the field when it appears (pointer devices; avoid on touch to keep the keyboard closed) |
SCommandList
Scrollable result list: max-h-[300px] overflow-y-auto.
| Prop | Type | Default | Description |
|---|---|---|---|
maxListHeight | number | 300 | max height before scrolling (vp) |
Slots: children (trailing closure)
SCommandEmpty
Shown when the query matches no item: py-6 text-center text-sm.
| Prop | Type | Default | Description |
|---|---|---|---|
text | ResourceStr | $r('app.string.spark_no_results') |
Slots: children (trailing closure)
SCommandGroup
overflow-hidden p-1 with an optional heading px-2 py-1.5 text-xs font-medium text-muted-foreground.
| Prop | Type | Default | Description |
|---|---|---|---|
heading | ResourceStr | undefined | undefined |
Slots: children (trailing closure)
SCommandSeparator
-mx-1 h-px bg-border; hidden while searching.
No props.
SCommandItem
One result row: relative flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm, accent background when highlighted (keyboard ↑/↓ or pointer hover — switches instantly, never cross-fades); a press only fades the row (a selection row: a pressed background next to the highlighted one would read as two highlights). Activation is the row's native onClick — tap, click, the screen reader, Space — plus Enter in the input (or on the focused row when the command has no input); it fires onSelect(value). A .onClick() chained on the item does not fire (the row's own click takes it).
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | '' | |
text | ResourceStr | '' | |
icon | string | undefined | undefined | |
shortcut | string | undefined | undefined | |
keywords | string[] | [] | extra search terms |
disabled | boolean | false | |
checked | boolean | undefined | undefined | undefined: no check slot; true / false: trailing check mark shown / reserved (Combobox) |
| Event | Type | Default | Description |
|---|---|---|---|
onSelect | (value: string) => void | () => { } |
SCommandDialog
shadcn-vue CommandDialog: a Command palette in a centred dialog (p-0 overflow-hidden).
Closes after an item is selected unless closeOnSelect: false. Long palettes use the data mode: SCommandDialog({ open: this.palette!!, items: COMMANDS, autoFocus: true, onItemSelect: ... }).
| Prop | Type | Default | Description |
|---|---|---|---|
open!! | boolean | undefined | undefined | |
defaultOpen | boolean | false | |
closeOnSelect | boolean | true | |
shouldFilter | boolean | true | |
title | ResourceStr | $r('app.string.spark_command_palette') | accessible title (shadcn renders it sr-only) |
items | SparkCommandEntryData[] | undefined | undefined | data mode (see SCommand): items of a virtualized palette instead of slot content |
placeholder | ResourceStr | $r('app.string.spark_command_placeholder') | |
emptyText | ResourceStr | $r('app.string.spark_no_results') | |
maxListHeight | number | 300 | |
autoFocus | boolean | false | data mode: focus the search field on open (pointer devices) |
| Event | Type | Default | Description |
|---|---|---|---|
onOpenChange | (open: boolean) => void | () => { } | |
onItemSelect | (value: string) => void | () => { } | fired after any item is selected (with its value) |
Slots: children (trailing closure)