Command
A search field over a list of actions or choices. Type to filter, move with the arrow keys, and press Enter to choose. Put it inline, inside a popover picker, or in a command palette dialog.
Command playground
Filter and select commands inline. Type to filter; arrow keys, Home, End, and Enter work from the search field.
Chosen: Nothing selected
Usage
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@tulipfarm/sprout/command";
<Command>
<CommandInput aria-label="Search sample commands" placeholder="Search sample commands…" />
<CommandList>
<CommandEmpty>No matching commands.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem onSelect={newDraft}>
<Plus size={16} aria-hidden="true" />
New draft
<CommandShortcut>⌘ N</CommandShortcut>
</CommandItem>
<CommandItem onSelect={openFolder}>
<Folder size={16} aria-hidden="true" />
Open folder
</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem disabled>Unavailable action</CommandItem>
</CommandGroup>
</CommandList>
</Command>Give the input an aria-label or pass label to Command. Each item matches on its text unless you pass a value, and onSelect receives that value. Groups and separators hide while nothing in them matches.
Command palette
CommandDialog pins a Command near the top of the screen in a 24rem dialog. Its title and description are visually hidden but announced. Escape closes it; add showCloseButton for a corner close button. Wire your own shortcut such as ⌘K to open it.
Command palette
CommandDialog pins a Command near the top of the screen. Its title and description are visually hidden; Escape closes it.
Last command: Nothing run yet
Pickers in a popover
Put a Command in PopoverContent size="menu" or size="picker"; both have no padding, so the search and list run edge to edge. Set data-checked on the current item to show a trailing check. Use a long value such as label plus description so both are searchable. Content after Command, such as an effort setting, stays outside the list.
Composer pickers
A Command inside a menu-size (24rem) and a picker-size (18rem) popover above the chat composer. The trailing check marks the current choice.
Ask about your workspace…
Controlled search and list states
Pass value and onValueChange to CommandInput to clear the search when the popover closes or from a button in CommandEmpty. When an item's value is an id, pass its name in keywords so it still matches. Show loading, error with retry, and empty-workspace notes as siblings after CommandList.
Project scope
A picker-size Command with a controlled search, an unlabeled first group, ids as values with names as keywords, and a recovery action when nothing matches.
No action yet
API
Command is a div that owns the search and the active item. It takes label, loop (wrap at the ends), shouldFilter (set false to filter items yourself), and filter(value, search, keywords), which returns a score where 0 hides the item. Matches are ranked: prefix, then word start, then substring, then letters in order. The default is exported as defaultCommandFilter.
CommandInput takes input props plus controlled value and onValueChange, and forwards ref. CommandList scrolls at 18rem. CommandEmpty renders only when nothing matches.CommandGroup takes an optional heading and forceMount. CommandSeparator hides while searching unless alwaysRender.
CommandItem takes value, keywords, disabled, onSelect, forceMount, and data-checked. CommandShortcut is a trailing hint and replaces the check. CommandDialog takes the Dialog root props plus title, description, showCloseButton, closeLabel, container, and className. Every part sets a data-slot.
Accessibility
The input is a combobox that controls the listbox. Focus stays in the input and the active option is announced through aria-activedescendant. Arrow keys move, Home and End jump to the ends, ⌘ or Ctrl with arrows jumps to the first or last item, Alt with arrows jumps between groups, Ctrl+N and Ctrl+P also move, and Enter chooses. Disabled items are skipped. Buttons inside the Command, such as Clear search, keep their own keys.
When nothing matches, the list drops its listbox role, the input reports aria-expanded="false", and the empty message and its actions read as ordinary content. Separators are decorative and hidden from assistive technology.
Highlight and check changes fade over 120ms and stop when reduced motion is requested. In forced-colors mode the active item gets an outline.
Theme tokens
Command uses --sprout-surface, --sprout-text, --sprout-muted, --sprout-line, --sprout-input, --sprout-hover, --sprout-focus, and the control and panel radii. It needs no brand color, so it looks the same with the neutral and TulipFarm themes in light and dark mode.