Askr
UI & Componentsexperimental

Combobox and Command

Use combobox and command with the current published Askr packages.

  • @askrjs/themes/combobox0.0.13
  • @askrjs/themes/command0.0.13

How to use combobox and command

Combobox and Command should use the standard themed surface unless the application is deliberately implementing its own design system on top of @askrjs/ui.

  1. Import the themed component from @askrjs/themes/components; use @askrjs/ui directly only when building a custom visual system.
  2. Keep combobox and command labels, state, and application actions visible at the call site instead of styling internal DOM nodes.
  3. Verify keyboard behavior, focus movement or return, disabled state, and both standard themes.
import { Combobox, ComboboxInput, ComboboxList, ComboboxOption } from '@askrjs/themes/components';

<Combobox value={owner()} onValueChange={owner.set}>
  <ComboboxInput aria-label="Project owner" />
  <ComboboxList>
    {people.map((person) => <ComboboxOption value={person.id}>{person.name}</ComboboxOption>)}
  </ComboboxList>
</Combobox>

Purpose

Combobox and Command give you the DOM shape and ARIA roles for a searchable dropdown list and a command palette, respectively — nothing more. Both ship only from @askrjs/themes, with no @askrjs/ui headless counterpart, because the interaction logic (filtering, keyboard navigation, open/close state) hasn't been built as a reusable primitive. That's why both are marked experimental: you're getting styled markup, not a finished widget.

Install and import

Pull `Combobox`, `ComboboxInput`, `ComboboxList`, and `ComboboxOption` from `@askrjs/themes/combobox`, and `Command`, `CommandDialog`, `CommandInput`, `CommandList`, `CommandGroup`, `CommandItem`, and related parts from `@askrjs/themes/command`. Both subpaths resolve to the same compiled components barrel as every other themed export, so there's nothing package-specific to configure beyond the import path. No `@askrjs/ui/combobox` or `@askrjs/ui/command` export exists — don't reach for one.

Live examples

Because neither component wires up state, a working example has to bring its own open/closed flag, filtered option list, and highlighted-index tracking before Combobox or Command look like more than styled containers. Treat any demo you build as a reference implementation of the missing behavior layer, not a copy-paste widget — you're writing the same keydown handlers and filter logic that libraries like cmdk normally hide.

Anatomy

Combobox composes `Combobox` (the outer slot), `ComboboxInput` (a real `<input>` with `role="combobox"`), `ComboboxList` (`role="listbox"`), and `ComboboxOption` (`role="option"`). Command composes `Command`, `CommandDialog` for the palette-in-a-dialog pattern, `CommandInput`, `CommandHeader`, `CommandList` (`role="listbox"`), `CommandEmpty` for the no-results state, `CommandGroup` (`role="group"`) with `CommandGroupHeading`, `CommandItem`, `CommandSeparator` (`role="separator"`), and `CommandShortcut` for a keybinding hint. Every part is a thin wrapper that sets a `data-slot` attribute and an ARIA role over whatever children you pass in.

State model

There isn't one built in — no internal `open`, `value`, or `activeIndex` state, and no context connecting the pieces together. `CommandItem` accepts `active`, `selected`, and `disabled` booleans that it turns into `aria-selected`, `aria-disabled`, and matching `data-*` attributes, but you decide which item is active and update those props on every render. Filtering the list as the user types, closing on outside click, and syncing the input value are all your code to write.

Keyboard and accessibility

The roles are correct out of the box — `combobox`/`listbox`/`option` for Combobox, `listbox`/`group`/`separator` for Command — so assistive tech announces the right structure once real content is in place. Arrow-key navigation, Enter-to-select, and Escape-to-close aren't implemented, so you'll need to attach your own `onKeyDown` handler to `ComboboxInput` or `CommandInput` and move `aria-selected`/`active` yourself, following the roving-tabindex pattern these roles expect.

Styling and tokens

Each part renders with a `data-slot` hook (`combobox-input`, `command-item`, `command-group-heading`, and so on) so you can target styles without touching internal DOM structure, matching the same theme contract as the rest of the catalog. `ComboboxInput` and `CommandInput` both apply the shared `input` class alongside their slot, so they pick up the same token-driven look as a plain `Input`.

API

All parts accept the generic `CatalogComponentProps` shape — `as`, `asChild`, `class`, `children`, `ref` — plus whatever native attributes you spread onto them; there are no component-specific prop types exported for either family. The one exception is `CommandItem`, which adds typed `active`, `selected`, and `disabled` booleans that map to ARIA and `data-*` state. If you're looking for a `ComboboxProps` or `CommandProps` type to build against, it doesn't exist yet.

Edge cases

`CommandEmpty` gives you a slot to render when a filtered query matches nothing, but nothing shows or hides it automatically — you have to conditionally render it based on your own filtered results. Because Combobox and Command render generic elements rather than a native `<select>`, they don't get free form participation; if a selected value needs to reach a native `<form>` submission, wire up a hidden input synced to your own state.

See Native Select if you just need a working, accessible picker with zero custom interaction code — a native `<select>` beats a hand-wired Combobox for most simple cases. See Menu, Dropdown, and Context Menu for a themed family that at least ships full keyboard handling for list-style overlays.