VayuUI

CommandBox

A command palette for quick navigation, search, and actions with keyboard shortcuts and fuzzy search.

Installation

npx vayu-ui init #one time only
npx vayu-ui add commandbox
npx vayu-ui add -t commandbox #with test case needs

Usage

Command Palette

Press Ctrl+Shift+P or click the button

Interactive

Use arrow keys to navigate, Enter to select, Escape to close

Inline CommandBox

Without overlay backdrop

Embedded

With Descriptions

Items with additional context

Simple List

Without groups or shortcuts

Loading State

Async command loading

Loading commands...
<CommandBox open={open} onOpenChange={setOpen} onSelect={handleSelect}>
  <CommandBox.Overlay>
    <CommandBox.Input placeholder="Type a command or search..." />
    <CommandBox.List>
      <CommandBox.Group label="Navigation">
        <CommandBox.Item
          id="home"
          shortcut={['⌘', 'H']}
          icon={<Home className="w-4 h-4" />}
        >
          Go to Home
        </CommandBox.Item>
        <CommandBox.Item
          id="search"
          shortcut={['⌘', 'S']}
          icon={<Search className="w-4 h-4" />}
        >
          Search
        </CommandBox.Item>
      </CommandBox.Group>

      <CommandBox.Separator />

      <CommandBox.Group label="Actions">
        <CommandBox.Item
          id="new-file"
          shortcut={['⌘', 'N']}
          icon={<Plus className="w-4 h-4" />}
        >
          New File
        </CommandBox.Item>
        <CommandBox.Item id="settings" icon={<Settings className="w-4 h-4" />}>
          Open Settings
        </CommandBox.Item>
      </CommandBox.Group>

      <CommandBox.Empty>No commands found.</CommandBox.Empty>
    </CommandBox.List>
  </CommandBox.Overlay>
</CommandBox>

Anatomy

import { CommandBox } from 'vayu-ui';

<CommandBox open={open} onOpenChange={setOpen}>
  <CommandBox.Overlay>
    <CommandBox.Input placeholder="Search..." />
    <CommandBox.List>
      <CommandBox.Group label="Section">
        <CommandBox.Item id="item-1" shortcut={['⌘', 'N']} icon={<Icon />}>
          Item Label
        </CommandBox.Item>
      </CommandBox.Group>
      <CommandBox.Separator />
      <CommandBox.Empty>No results found.</CommandBox.Empty>
    </CommandBox.List>
  </CommandBox.Overlay>
</CommandBox>;
  • CommandBox — Root container. Manages open/close state, search filtering, and keyboard navigation.
  • CommandBox.Overlay — Portal-based overlay with backdrop. Renders the command box centered on screen.
  • CommandBox.Input — Search input with combobox ARIA role. Handles arrow key navigation and Enter selection.
  • CommandBox.List — Scrollable listbox container for items and groups.
  • CommandBox.Group — Groups items under a sticky label header.
  • CommandBox.Item — Individual option with support for icons, descriptions, keyboard shortcuts, and disabled state.
  • CommandBox.Separator — Visual divider between groups.
  • CommandBox.Empty — No-results message shown when search yields no matches.

Accessibility

  • Keyboard Support:
    • ArrowDown — Move highlight to the next item.
    • ArrowUp — Move highlight to the previous item.
    • Enter — Select the highlighted item and close the palette.
    • Home — Jump highlight to the first item.
    • End — Jump highlight to the last item.
    • Escape — Close the palette.
    • Modifier shortcuts (e.g., ⌘+N, Ctrl+K) — Select the matching item directly.
  • ARIA Attributes:
    • Input has role="combobox" with aria-expanded, aria-controls, and aria-activedescendant.
    • List has role="listbox" linked via aria-controls.
    • Each item has role="option" with aria-selected and aria-disabled.
    • Groups use role="group" with aria-label.
    • Separator uses role="separator" with aria-orientation="horizontal".
    • Empty state uses role="status" with aria-live="polite".
    • Backdrop is marked aria-hidden="true".
  • Focus Behavior:
    • Input auto-focuses when the palette opens.
    • Highlighted item scrolls into view automatically.
    • Body scroll is locked while the palette is open.

Screen reader behavior

When the command palette opens, the screen reader announces the search input as a combobox. As the user types, filtered results update in the live region. The highlighted item is announced via aria-activedescendant on the input. Each option is announced with its role ("option") and selected state. Group labels are announced when navigating into a new group via aria-label on the group container. The empty state message is announced through the aria-live="polite" region when no results match. When the palette closes, focus returns to the previously focused element.

Component Folder Structure

CommandBox/
├── CommandBox.tsx            # Root component with state management and filtering
├── CommandBoxInput.tsx       # Search input with combobox ARIA role
├── CommandBoxList.tsx        # Scrollable listbox container
├── CommandBoxItem.tsx        # Self-registering option with selection states
├── CommandBoxGroup.tsx       # Grouped items with sticky label header
├── CommandBoxSeparator.tsx   # Visual divider between groups
├── CommandBoxEmpty.tsx       # No-results state with aria-live
├── CommandBoxOverlay.tsx     # Portal-based overlay with backdrop
├── hooks.ts                  # Context provider and fuzzy search utility
├── types.ts                  # TypeScript type definitions
└── index.ts                  # Re-exports all components and types

Props

CommandBox (Root)

PropTypeDefaultDescription
openbooleanControlled open state.
defaultOpenbooleanfalseInitial open state for uncontrolled mode.
onOpenChange(open: boolean) => voidCallback when open state changes.
onSelect(item: CommandBoxItemData) => voidCallback when an item is selected.
filter(item, search) => numberCustom filter scoring function.
showShortcutsbooleantrueShow keyboard shortcut badges on items.
loadingbooleanfalseShow loading state.
childrenReactNodeComponent children.
classNamestringAdditional CSS classes.

CommandBox.Input

PropTypeDefaultDescription
placeholderstring'Type a command or search...'Input placeholder text.
iconReactNode<Search />Custom search icon.
classNamestringAdditional CSS classes.

CommandBox.List

PropTypeDefaultDescription
maxHeightstring'320px'Maximum height before scrolling.
classNamestringAdditional CSS classes.

CommandBox.Item

PropTypeDefaultDescription
idstringUnique identifier. Required.
disabledbooleanfalseDisable selection.
shortcutstring[]Keyboard shortcut keys (e.g., ['⌘', 'N']).
iconReactNodeIcon displayed before the label.
descriptionstringSecondary description text.
titlestringItem title (falls back to children if string).
classNamestringAdditional CSS classes.

CommandBox.Group

PropTypeDefaultDescription
labelstringGroup heading label. Required.
classNamestringAdditional CSS classes.

CommandBox.Empty

PropTypeDefaultDescription
childrenReactNode'No results found'Custom empty state message.
classNamestringAdditional CSS classes.

CommandBox.Separator

PropTypeDefaultDescription
classNamestringAdditional CSS classes.

CommandBox.Overlay

PropTypeDefaultDescription
childrenReactNodeContent to render inside.
classNamestringAdditional CSS classes.

On this page