Command

Finds and runs commands inline or in a native dialog. Filter by typing or supply ranked results; navigate with arrows and Enter.

Go to
Components⌘1
Tokens⌘2

Jump

⌘K

Jump the catalog without leaving the sheet.

Use it for

  • A palette of commands and destinations behind one shortcut.
  • keywords on an item to widen the match; hint for the shortcut label and description for one concise secondary line.
  • Supply a stable item id when commands share a visible label; it identifies rows and changes in result order.
  • Control the query with value and onValueChange, or initialize it with defaultValue. Set inputLabel to name the search field.
  • Set shouldFilter={false} when the application supplies ranked groups. Their order is preserved; query and result changes reset the active option.

Not for

  • Picking a value for a field; use Combobox.
  • Fewer than ten commands; use DropdownMenu.

Three ways in. They share one source, so the pixels match whichever you pick.

1. Import the package

npm install @noorddev/vlak-react

// once, next to your app's root
import "@noorddev/vlak-react/css";

import { CommandDialog } from "@noorddev/vlak-react";

Precompiled React and one stylesheet. No compiler to configure. Per-component imports work too: @noorddev/vlak-react/components/command.

2. Vendor the source

npx @noorddev/vlak-cli add command

The StyleX leaf lands in components/vlak/ with its dependencies, for your own compiler to own. See StyleX.

3. Through shadcn

npx shadcn add https://vlak.dev/r/command.json

The same registry item, installed by shadcn's CLI.

CSS only

<link rel="stylesheet" href="node_modules/@noorddev/vlak/css/vlak.css" />

No React. Link vlak.css and use the markup and classes below.

import { useEffect, useState } from "react";
import { CommandDialog } from "@noorddev/vlak-react";

const [open, setOpen] = useState(false);

// wire the shortcut once in your app
useEffect(() => {
  const onKey = (e: KeyboardEvent) => {
    if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
      e.preventDefault();
      setOpen(true);
    }
  };
  window.addEventListener("keydown", onKey);
  return () => window.removeEventListener("keydown", onKey);
}, []);

<CommandDialog
  open={open}
  onClose={() => setOpen(false)}
  groups={[
    { label: "Go to", items: [{ label: "Components", description: "Browse components and usage", hint: "⌘1", onSelect: () => go("/components") }] },
    { label: "Actions", items: [{ label: "New project", keywords: "create add", onSelect: create }] },
  ]}
/>

Command

Search, arrows, enter. The input keeps focus; the list is aria-activedescendant.

PropTypeDefaultDescription
groupsrequiredCommandGroup[]
valuestring
defaultValuestring""
onValueChange(value: string) => void
placeholderstring"Type a command or search…"
inputLabelstring"Command"
shouldFilterbooleantrueDisable built-in filtering when the application supplies ranked results.
emptyLabelReactNode"Nothing found."
onDone() => void

Also accepts Omit<HTMLAttributes<HTMLDivElement>, "defaultValue">.

CommandDialog

The palette in a native <dialog>. Wire ⌘K in your app to setOpen(true).

PropTypeDefaultDescription
groupsrequiredCommandGroup[]
valuestring
defaultValuestring
onValueChange(value: string) => void
placeholderstring
inputLabelstring
shouldFilterbooleanDisable built-in filtering when the application supplies ranked results.
emptyLabelReactNode
onDone() => void
openrequiredboolean
onClose() => void

Also accepts Omit<HTMLAttributes<HTMLDivElement>, "defaultValue">.

KeysDoes
TypeUpdates the search; filters labels and keywords unless shouldFilter is false
Arrow down, Arrow upMoves the active item
Home, EndFirst or last item
Page up, Page downMoves ten items
EnterRuns the active item and closes, except while composing text with an IME
EscapeCloses
<div class="rs-command" style="border:1px solid var(--divider);border-radius:var(--radius)"><input class="rs-command-input" placeholder="Type a command or search…" /><div class="rs-command-list" role="listbox"><div class="rs-command-group">Go to</div><div class="rs-command-item rs-command-item-active" role="option" aria-selected="true"><span>Components</span><span class="rs-command-hint rs-command-hint-active">⌘1</span></div><div class="rs-command-item" role="option" aria-selected="false"><span>Tokens</span><span class="rs-command-hint">⌘2</span></div></div></div>
.rs-command.rs-command-input.rs-command-list.rs-command-group.rs-command-item.rs-command-item-active.rs-command-content.rs-command-description.rs-command-description-active.rs-command-hint.rs-command-hint-active.rs-command-empty