Skip to main content

Command

A composable command menu with built-in search filtering, keyboard navigation, and group support.

import * as Command from '@gentleduck/primitives/command'
import * as Command from '@gentleduck/primitives/command'

Anatomy

<Command.Root>
  <Command.Input />
  <Command.List>
    <Command.Empty />
    <Command.Group>
      <Command.Item />
    </Command.Group>
    <Command.Separator />
  </Command.List>
</Command.Root>
<Command.Root>
  <Command.Input />
  <Command.List>
    <Command.Empty />
    <Command.Group>
      <Command.Item />
    </Command.Group>
    <Command.Separator />
  </Command.List>
</Command.Root>

Example

import * as Command from '@gentleduck/primitives/command'
 
function CommandMenu() {
  return (
    <Command.Root className="rounded-lg border shadow-md">
      <Command.Input placeholder="Type a command or search..." />
      <Command.List>
        <Command.Empty>No results found.</Command.Empty>
        <Command.Group heading="Suggestions">
          <Command.Item onSelect={() => console.log('Calendar')}>Calendar</Command.Item>
          <Command.Item onSelect={() => console.log('Search')}>Search</Command.Item>
        </Command.Group>
        <Command.Separator />
        <Command.Group heading="Settings">
          <Command.Item onSelect={() => console.log('Profile')}>Profile</Command.Item>
          <Command.Item onSelect={() => console.log('Settings')}>Settings</Command.Item>
        </Command.Group>
      </Command.List>
    </Command.Root>
  )
}
import * as Command from '@gentleduck/primitives/command'
 
function CommandMenu() {
  return (
    <Command.Root className="rounded-lg border shadow-md">
      <Command.Input placeholder="Type a command or search..." />
      <Command.List>
        <Command.Empty>No results found.</Command.Empty>
        <Command.Group heading="Suggestions">
          <Command.Item onSelect={() => console.log('Calendar')}>Calendar</Command.Item>
          <Command.Item onSelect={() => console.log('Search')}>Search</Command.Item>
        </Command.Group>
        <Command.Separator />
        <Command.Group heading="Settings">
          <Command.Item onSelect={() => console.log('Profile')}>Profile</Command.Item>
          <Command.Item onSelect={() => console.log('Settings')}>Settings</Command.Item>
        </Command.Group>
      </Command.List>
    </Command.Root>
  )
}

API

Command.Root

The root container that manages search state, filtering, and keyboard navigation. Renders a <div>.

PropTypeDefaultDescription
dir'ltr' | 'rtl'--Text direction
shouldFilterbooleantrueEnable internal search filtering
asChildboolean--Render as child element

Command.Input

The search input field. Renders an <input>.

PropTypeDefaultDescription
asChildboolean--Render as child element

Accepts all standard HTML input attributes.

Command.List

Container for items and groups. Renders a <ul>. Handles internal filtering and item visibility based on the search value.

PropTypeDefaultDescription
asChildboolean--Render as child element

Command.Item

A selectable item within the list. Renders a <li>.

PropTypeDefaultDescription
valuestring--Item value passed to onSelect
disabledbooleanfalseDisables the item
textValuestring--Text for search matching (auto-derived from text content if not provided)
onSelect(value: string) => void--Called when the item is selected
asChildboolean--Render as child element

Command.Group

Groups items with an optional heading. Renders a <div>. Items inside a group are hidden when none match the search.

PropTypeDefaultDescription
headingReact.ReactNode--Optional group heading
asChildboolean--Render as child element

Command.Empty

Displays when all items are filtered out. Renders a <div>.

PropTypeDefaultDescription
asChildboolean--Render as child element

Command.Separator

A visual separator between groups. Renders a <div>. Hidden when adjacent groups have no visible items.

PropTypeDefaultDescription
asChildboolean--Render as child element

Hooks

useCommandContext()

Access the command state from within Command.Root.

Returns: { search, selectedItem, selectedValue, selectedText }