Skip to content

Command

Command implements the cmdk pattern from scratch: a bordered surface holding a search input, a scrollable list, and items that filter against the query (case-insensitive Contains by default). Items and groups register with the root via a cascading context so a group hides when none of its items match and ZitsCommandEmpty shows when nothing does. It composes no Navius primitive; all filtering, active-item tracking, and keyboard handling are the component’s own C#.

Terminal window
navius add command --to ./src/MyApp --namespace MyApp.Ui
@using Zits.Ui.Components
<ZitsCommand @bind-Query="_query" class="w-full max-w-[450px]">
<ZitsCommandInput Placeholder="Type a command or search..." />
<ZitsCommandList>
<ZitsCommandEmpty>No results found.</ZitsCommandEmpty>
<ZitsCommandGroup Heading="Suggestions">
<ZitsCommandItem Value="Calendar" OnSelect="OnSelect">Calendar</ZitsCommandItem>
<ZitsCommandItem Value="Calculator" Disabled OnSelect="OnSelect">Calculator</ZitsCommandItem>
</ZitsCommandGroup>
<ZitsCommandSeparator />
<ZitsCommandGroup Heading="Settings">
<ZitsCommandItem Value="Profile" OnSelect="OnSelect">
Profile
<ZitsCommandShortcut>⌘P</ZitsCommandShortcut>
</ZitsCommandItem>
</ZitsCommandGroup>
</ZitsCommandList>
</ZitsCommand>
@code {
private string _query = string.Empty;
private void OnSelect(string value) { }
}

ZitsCommand (root)

Prop Type Default Description
Query / QueryChanged string "" The search query. Bind with @bind-Query.

ZitsCommandInput

Prop Type Default Description
Placeholder string? null Placeholder text for the search field.

ZitsCommandList

Prop Type Default Description
AriaLabel string "Suggestions" Accessible name for the listbox.

ZitsCommandGroup

Prop Type Default Description
Heading string? null Section heading; the whole group (heading included) hides when none of its items match.

ZitsCommandItem

Prop Type Default Description
Value string "" Text matched against the query, and the value passed to OnSelect.
Selected bool false Marks the row as selected independent of keyboard/mouse activity.
Disabled bool false Excludes the row from navigation, filtering match, and click.
OnSelect EventCallback<string> Fired on click, or Enter while the row is the active row.

ZitsCommandEmpty, ZitsCommandSeparator, ZitsCommandShortcut take only ChildContent/Attributes; they render conditionally (Empty) or are purely presentational (Separator, Shortcut).

Every part accepts class via Attributes, merged with its base class through Cn.Merge.

Part Attribute Description
Item data-active / data-highlighted Present on the virtually-active row (keyboard highlight or hover).
Item data-selected Present when Selected is set.
Item data-disabled Present when Disabled is set; also drives pointer-events-none styling.

Command wires its own ARIA mechanism: the input carries role="combobox", aria-expanded="true", aria-controls pointing at the list’s id, and aria-activedescendant pointing at the current active item’s id. The list is role="listbox" with an accessible name from AriaLabel; groups are role="group" and hide via the hidden attribute when empty; items are role="option" with aria-selected. Keyboard handling lives on the input: ArrowDown/ArrowUp move the active item (wrapping), Home/End jump to the ends, Enter invokes the active item’s OnSelect, and Escape clears a non-empty query (a no-op otherwise, so a hosting dialog can still close on Escape). Hovering a row also makes it active. The active row is scrolled into view through the engine’s NaviusJsInterop.ScrollIntoViewByIdAsync (CSP-safe, no eval).