Noctis

Command

A command palette: a query field over a ranked list of commands with full keyboard navigation, grouped sections, and breadcrumb drill-in. Built on a combobox/aria-activedescendant core so the input keeps focus while a virtual cursor moves the active row. Ranking is owned by the design system — rank your commands with the exported rankItems and render the survivors as Command.Items — and fully escapable when you need your own order.

A complete palette

Everything at once, the way you'd ship it: a modal launcher over grouped, fuzzy-ranked sections, each row an icon · label · shortcut, with Switch network… and Transfer assets… drilling into sub-pages (Backspace or the breadcrumb steps back out). Open it from the trigger and type to watch the panel re-rank and resize.

The batteries-included launcher. Command.Dialog is a focus-trapped modal (portal, blurred backdrop, scroll-lock, Esc to close); a headless Command.Trigger wires open-state and ARIA onto your own button. Wire the same open/onOpenChange to both. The footer carries keyboard hints. In your own app you'd bind a global ⌘K to open it (omitted in these docs so the demos don't fight this site's own ⌘K palette).

Inline

Command.Root embeds the same palette in normal flow — a page, a sidebar, a settings panel — with no modal chrome. It shares every inner part with the dialog.

Create universal address
Transfer assets
Withdraw from vault
Add webhook endpoint
Copy settlement ID

Rows with icons

Lead each row with a Command.ItemIcon wrapping an Icon — a glyph column that quiets to the muted role and lines up under the input's search glyph. The icon is the only opinion the row takes; everything after Command.ItemLabel is yours. Drop a Kbd straight in and the label's flex pushes it to the row's end, so the row reads icon · label · keys, left to right.

Create universal addressc
Transfer assetst
Withdraw from vaultw
Rotate API keyCommandr
Copy settlement IDCommandc
Open documentation

Sections and shortcuts

Group rows with Command.Group and a Command.GroupLabel heading. For a keyboard hint, put a Kbd after the label — the component has no "shortcut" part, so you compose the caps yourself: single keys, chords (Alt+C), and sequences (G then I) all render exactly how you format them. Rank within each group and drop empty sections.

Addresses
Create universal addressc
Refresh addressesCommandr
Vaults
Deposit to vaultd
Withdraw from vault
Navigation
Go to settlementsg then s
Go to walletsg then w

Drill-in

Selecting a parent command pushes a page: the list swaps to its children with a fresh, empty query, and a Command.Breadcrumb segment appears. Backspace on the empty query — or clicking an earlier segment — pops back out and restores the query you had typed at that level (each view keeps its own). The pages stack is controlled, so you drive which children load (including async).

Switch network…
Filter by asset…
Refresh wallet
Export transactions

Ranking

The palette ships a fuzzy scorer tuned for command bars: a contiguous prefix beats a gapped match, a word-boundary hit beats one mid-word, and keywords let a row answer to hidden aliases. rankItems(items, query) returns the filtered, ordered survivors — feed it your command list and map the result to Command.Items. Blend in usage recency through a per-item boost, or pass your own score function (or sorted list) to take over ordering entirely. For very large lists, useCommandRanking offloads scoring to a Web Worker with a synchronous fallback.

Looping

Arrow-key navigation stops at the ends of the list by default — a command bar shouldn't quietly jump you from the last row back to the first. Pass loop to opt into cycling: ArrowDown past the last row wraps to the first (through the input, per the ARIA combobox pattern) and ArrowUp from the first wraps to the last.

Create universal address
Transfer assets
Withdraw from vault
Refresh settlements
Open documentation

Theme scope

ThemeScope re-tunes a whole region's shape — corner radius, density, and type scale — through the cascade, with no per-component prop and without touching the app-wide theme. Tweak the knobs below, then open the command palette: the floating panel re-tunes too, even though it portals to <body>, because the scope rides a portal-safe context. See Customization for nesting, reset, and the raw-token portal caveat.

Motion

The panel is auto-height: it grows and shrinks with its list as you type, so the palette glides between sizes instead of snapping. A ResizeObserver measures the rendered rows and feeds the height into the list, which tweens its block-size; once the panel reaches its cap the list scrolls past it behind a thin scrollbar. Reaching the first or last row scrolls it to the very edge — the list's inner padding (and a group label above the first row) stays in view rather than the row sitting cropped against the edge. Drilling into a sub-page cross-fades the new view in as the old one gives way. The animations honour prefers-reduced-motion.

Keyboard

The input keeps focus throughout; a virtual cursor (aria-activedescendant) moves the active row.

KeyAction
TypeFilters and re-ranks; the highlight follows the same row, dropping to the top result only when that row is filtered out
Down arrow Up arrowMove the active row by one
CommandDown arrow CommandUp arrowJump to the last / first row (AltDown arrow / AltUp arrow too)
Home EndJump to the first / last row
PageUp PageDownMove by a page of rows
Controlp ControlnMove up / down, emacs-style (Controlk / Controlj too)
EnterActivate the highlighted command
BackspaceOn an empty query, step back out of a drill-in page
EscapeClose the modal palette
CommandkOpen the palette (wire it yourself, as the modal example does)

By default the active row stops at the ends of the list; pass loop to wrap (a held arrow still stops at the edge — only a fresh press wraps). See Looping.

Accessibility

The input is a role="combobox" that keeps DOM focus; the list is a role="listbox" and each row a role="option". A virtual cursor moves aria-activedescendant to the active row, so screen readers announce it without focus ever leaving the field — the WAI-ARIA pattern for a command palette. The modal is named by a visually-hidden title (label, defaulting to the localized command.label string), traps focus, and locks scroll. Render Command.Empty (a polite live region) when your ranked list is empty so the no-results state is announced. The headless Command.Trigger stamps aria-haspopup="dialog" and reflects aria-expanded. RTL is structural — logical properties throughout.

Anatomy

Compose the palette from its parts; both Command.Dialog and Command.Root share the same inner set.

  • Command.Dialog — the modal launcher (portal, backdrop, focus trap). Takes open/onOpenChange, the controlled query, and the pages stack.
  • Command.Root — the inline panel; same props, no modal chrome.
  • Command.Trigger — a headless launcher that wires onClick + ARIA onto your own element via render.
  • Command.Header — the input row; holds a Command.Breadcrumb, a leading glyph, the Command.Input, and an optional Command.InputAction.
  • Command.Breadcrumb — the drill-in trail; renders the pages stack and pops it.
  • Command.Input — the query field; Backspace on empty pops a page.
  • Command.InputAction — a trailing affordance slot in the input row.
  • Command.List — the scrolling listbox.
  • Command.Group / Command.GroupLabel — a labelled section and its heading.
  • Command.Item — a command row, activated by click or Enter (onSelect); compose a Command.ItemIcon and a Command.ItemLabel, then any trailing content (a Kbd, a badge) which the label pushes to the row's end.
  • Command.Separator — a divider between sections.
  • Command.Empty / Command.Loading — the no-results and async-progress messages.
  • Command.Footer — a bare footer region; compose your own status or hints inside.

Every rendered part carries a data-slot (noctis-command on the panel, noctis-command-item on a row, …) for host-side styling, off which the precompiled command.css keys each rule.

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The minted tokens are the public override seam: set one on any ancestor and every palette in that region retunes. See Customization for the override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table.

Command.Root

Prop

Command.Dialog

Prop

Command.Trigger

Prop

Command.Header

Prop

Command.Breadcrumb

Prop

Command.Input

Prop

Command.InputAction

Prop

Command.List

Prop

Command.Group

Prop

Command.GroupLabel

Prop

Command.Item

Prop

Command.ItemIcon

Prop

Command.ItemLabel

Prop

Command.Separator

Prop

Command.Empty

Prop

Command.Loading

Prop

Command.Footer

Prop

AttributeDescription
data-slotMarks each rendered part.
data-modalPresent on the panel in its modal form (the centred, fixed-height, scale-fading popup).
data-highlightedPresent on the command row the pointer or keyboard is currently over (the active descendant).
data-disabledPresent on a disabled command row.
data-starting-stylePresent on the modal panel/scrim for the first frame after mount — the transition's start state.
data-ending-stylePresent on the modal panel/scrim while it transitions out before unmounting.