Command

A searchable list of commands with groups, keyboard navigation and shortcuts. Use it inline, or as a ⌘K command palette with Command.Dialog.

BetaSource

Last command: nothing yet

Import

import { Command } from "@meridui/react";

Anatomy

<Command.Root>
  <Command.Input />
  <Command.List>
    <Command.Empty />
    <Command.Group heading="…">
      <Command.Item />
    </Command.Group>
    <Command.Separator />
  </Command.List>
</Command.Root>

<Command.Dialog>{/* the same parts */}</Command.Dialog>
  • Root holds the search text and the active item, filters items and handles the keys.
  • Input is the search box (role="combobox"). Focus stays in it; the active item is announced with aria-activedescendant.
  • List is the role="listbox" of results. Item is an option; Group adds a heading.
  • Empty renders only when nothing matches. Separator hides while a search is typed.
  • Dialog wraps everything in a modal Dialog that opens with ⌘K / Ctrl+K.

Examples

Command palette

Command.Dialog registers a global shortcut (default ["mod", "k"]; pass shortcut={null} to turn it off), focuses the input on open and closes after an item is chosen (closeOnSelect). This site already uses ⌘K for its own search, so the demo uses ⌘J.

Last command: nothing yet

Filtering

By default every word of the search must appear in the item's value or its keywords, ignoring case and accents ("cafe" finds "Café"). Pass filter to match differently, or shouldFilter={false} when you filter on the server and render only the matching items.

<Command.Root filter={(value, search) => value.toLowerCase().startsWith(search.toLowerCase())}>

Item shortcuts

shortcut shows the keys with Shortcut and, while the command menu has focus, pressing them runs the item. Shortcuts need a modifier (⌘, Ctrl or Alt) so typing is never hijacked.

API reference

Root

Accepts every <div> attribute except onSelect.

PropTypeDefaultDescription
searchstring–Controlled search text.
defaultSearchstring""Initial search text when uncontrolled.
onSearchChange(search: string) => void–Called when the search text changes.
filter(value, search, keywords) => boolean–Custom match function. Defaults to case- and accent-insensitive word matching.
shouldFilterbooleantrueSet to false to filter items yourself.
loopbooleantrueWrap from the last item to the first with the arrow keys.
onSelect(value: string) => void–Called with the value of any chosen item, after the item's own onSelect.
labelstring"Command menu"Accessible name of the search box.
resultsLabel(count: number) => string"N results"Status announced to screen readers while searching.
shortcutLabelsShortcutKeyLabels–Spoken key names for item shortcuts, merged over the English defaults.
refRef<HTMLDivElement>–Forwarded ref to the root element.

Input

Accepts every <input> attribute except value, defaultValue, onChange and type: the search text lives on Root.

PropTypeDefaultDescription
placeholderstring"Type a command or search…"Placeholder text.
onValueChange(search: string) => void–Called with the new search text.
refRef<HTMLInputElement>–Forwarded ref to the input.

List, Empty, Group, Separator

PropTypeDefaultDescription
List labelstring"Suggestions"Accessible name of the listbox.
Empty childrenReactNode"No results found."Shown when no item matches.
Group headingReactNode–Visible heading; also names the group.
Separator alwaysRenderbooleanfalseKeep the separator while a search is typed.

Item

Accepts every <div> attribute except onSelect.

PropTypeDefaultDescription
valuestring–Unique value used for filtering and onSelect. Defaults to the text when children is a string.
keywordsstring[]–Extra search terms that also match.
onSelect(value: string) => void–Called when the item is chosen by click, Enter or its shortcut.
disabledbooleanfalseSkipped by the arrow keys and ignores clicks.
leadingReactNode–Icon shown before the label.
shortcutstring[]–Keys shown after the label, e.g. ["mod", "s"]; they also run the item.
refRef<HTMLDivElement>–Forwarded ref to the option.

Dialog

Takes every Root prop plus:

PropTypeDefaultDescription
openboolean–Controlled open state.
defaultOpenbooleanfalseInitial open state when uncontrolled.
onOpenChange(open: boolean) => void–Called when the open state should change.
shortcutstring[] | null["mod", "k"]Global key combination that toggles the dialog; null disables it.
closeOnSelectbooleantrueClose the dialog after an item is chosen.
containerElement | nulldocument.bodyPortal target.

Styling

ClassElement
.mrd-commandRoot
.mrd-command__input-wrap, .mrd-command__inputSearch row and input
.mrd-command__listList
.mrd-command__group, .mrd-command__headingGroup and its heading
.mrd-command__itemItem
.mrd-command__leading, .mrd-command__label, .mrd-command__shortcutItem parts
.mrd-command__empty, .mrd-command__separatorEmpty and Separator
.mrd-command-dialogDialog surface
AttributeOnValues
data-activeItempresent on the active item
data-disabledItempresent when disabled
data-valueItemthe item's value

Accessibility

Follows the WAI-ARIA Combobox pattern with a listbox that is always shown. Focus never leaves the input; the active option is conveyed with aria-activedescendant, and the number of results is announced in a polite live region. When nothing matches, the list stops being a listbox and the input reports aria-expanded="false". Every announced string is a prop.

KeyAction
ArrowDownNext item, wrapping (skips disabled items).
ArrowUpPrevious item, wrapping.
PageUpFirst item.
PageDownLast item.
EnterRun the active item.
⌘ / CtrlKCommand.Dialog: open or close from anywhere.
EscapeCommand.Dialog: close and return focus.

Guidelines

Do

Name items with a verb or a destination ("New project", "Go to billing") and group them by kind.

Avoid

Make the command menu the only way to reach an action. It is a shortcut for people who know what they want.

  • Shortcut: key combinations shown in items.
  • Dialog: the modal behind Command.Dialog.
  • Select: choose one value for a form.