Rime

Command

A command palette: a search box over grouped actions with shortcuts, keyboard-first, inline or as a Ctrl+K dialog.

Command is a combobox over a grouped listbox. Typing filters every group (every word must appear in the label or the item's keywords), Up and Down move the highlight, Enter runs it, and an empty state says when nothing matches. Focus stays in the input throughout; the highlighted option is announced through aria-activedescendant.

CommandDialog lifts it over the page in the modal glass and toggles it with Ctrl+K or Cmd+K (shortcut, on by default). Running a command closes it; Esc and the scrim close it too, and focus returns to where it was.

inline renders the open panel in the page flow: no portal, scrim, focus trap, scroll lock or outside-click listener. It exists for docs, previews and static mock-ups; never ship it as the live overlay.

Installation

npx shadcn@latest add KezLahd/rime/command

Also installs: alert-dialog, base, icon, scroll-area.

Usage

import { Command, CommandDialog } from "@/components/ui";

<CommandDialog
  open={open}
  onOpenChange={setOpen}
  groups={[
    { heading: "Suggestions", items: [{ id: "invoice", label: "Create invoice", shortcut: "Ctrl N", onSelect: create }] },
    { heading: "Go to", items: [{ id: "orders", label: "Orders", onSelect: () => router.push("/orders") }] },
  ]}
/>

Examples

Palette

Type to filter; arrows and Enter run a command.
Create invoiceCtrl N
Open calendar
Compose message
DashboardG D
Team membersG T
OrdersG O
Profile

As a dialog with Ctrl+K

Press the button, or Ctrl K anywhere on this page.

API

Generated from the component's TypeScript types and JSDoc (scripts/gen-ui-registry.mjs), so it always matches the source.

Command

Command props
PropTypeDefaultDescription
groupsRequiredReadonlyArray<CommandGroup>
labelstring"Search commands"The input's accessible name.
placeholderstring"Type a command or search…"
emptyTextReactNode"No results found."Shown when nothing matches.
onSelect(item: CommandItem) => voidCalled with the item after its own onSelect runs.
querystringControlled query. Leave unset for uncontrolled.
onQueryChange(q: string) => void
autoFocusbooleanFocus the input on mount.
classNamestring

CommandDialog

CommandDialog props
PropTypeDefaultDescription
labelstringThe input's accessible name.
classNamestring
onSelect(item: CommandItem) => voidCalled with the item after its own onSelect runs.
placeholderstring
groupsRequiredReadonlyArray<CommandGroup>
emptyTextReactNodeShown when nothing matches.
querystringControlled query. Leave unset for uncontrolled.
onQueryChange(q: string) => void
openRequiredboolean
onOpenChangeRequired(open: boolean) => void
shortcutbooleantrueToggle with Ctrl+K or Cmd+K from anywhere on the page. On by default.
inlinebooleanRender the open palette in the page flow: no portal, scrim, focus trap or shortcut (docs, previews).

Theme tokens

Per-component tokens are undeclared by default, so the default shown is the fallback the CSS uses. Set one at :root (or in theme.css) to restyle every instance. Live values are read from this page, so they follow the Rime Studio.

Command per-component tokens
TokenDefaultLive value
--command-dialog-width560px…
--command-input-h48px…
--command-list-max320px…
--command-radiusvar(--r-lg)…
--command-width440px…
--popover-item-active-bglinear-gradient(to right, rgba(var(--rgb-brand), 0.14), rgba(var(--rgb-brand-deep), 0.07))…
--popover-item-radiusvar(--r-xs)…
--popover-padcalc(6px * var(--density))…

System tokens it reads

Command system tokens
TokenDefaultLive value
--border-wtokens.css…
--densitytokens.css…
--durtokens.css…
--dur-slowtokens.css…
--easetokens.css…
--ease-outtokens.css…
--font-bodytokens.css…
--ink-bodytokens.css…
--ink-brandtokens.css…
--ink-disabledtokens.css…
--ink-headingtokens.css…
--ink-mutedtokens.css…
--ink-placeholdertokens.css…
--linetokens.css…
--line-glasstokens.css…
--line-softtokens.css…
--modal-blurtokens.css…
--modal-scrimtokens.css…
--modal-scrim-blurtokens.css…
--modal-shadowtokens.css…
--modal-surfacetokens.css…
--popover-blurtokens.css…
--popover-bordertokens.css…
--popover-shadowtokens.css…
--popover-surfacetokens.css…
--r-2xstokens.css…
--r-lgtokens.css…
--r-xstokens.css…
--rgb-brandtokens.css…
--rgb-brand-deeptokens.css…
--rgb-whitetokens.css…
--text-captiontokens.css…
--text-inputtokens.css…
--text-microtokens.css…
--text-smalltokens.css…
--tracking-labeltokens.css…
--z-modaltokens.css…

Accessibility

  • The input is role="combobox" with aria-controls and aria-activedescendant; results are role="listbox" with role="group" sections labelled by their headings and role="option" rows.
  • The result count is announced through a polite status region as you type.
  • CommandDialog is a modal dialog: focus moves to the input, Tab is trapped, Esc closes, focus returns.

Do and don't

Do

  • Add keywords for the words people actually type ("new", "add").
  • Show the real shortcut beside each command that has one.

Don't

  • Don't make the palette the only way to reach a page.
  • Don't fill it with every possible action; keep the top group to what is likely now.

For AI agents

This page as markdown, rendered from the same registry entry. Point an agent at it (or add .md to this page's URL), or at /llms.txt for the index.

Open command.md

Related: nav-search, menu