Askr documentation
UI & Componentsexperimental

Combobox and Command

Combobox and Command: anatomy, keyboard behavior, state, and theming in Askr.

Example

import { For } from '@askrjs/askr/control';
import { Combobox, ComboboxInput, ComboboxList, ComboboxOption } from '@askrjs/themes/components';

<Combobox value={owner()} onValueChange={setOwner}>
  <ComboboxInput aria-label="Project owner" />
  <ComboboxList>
    <For each={people} by={(person) => person.id}>
      {(person) => <ComboboxOption value={person.id}>{person.name}</ComboboxOption>}
    </For>
  </ComboboxList>
</Combobox>
Try Combobox

Filter and select an owner from a searchable list.

Maya
Leo
Sam

Published props

Generated from the TypeScript declarations shipped by the installed package. Named types in the Type column define the accepted values.

CommandPaletteContentProps

Import from @askrjs/themes/command.

PropTypeDefaultDescription
childrenchildren?: unknown;——
closeOnBackdropcloseOnBackdrop?: boolean | undefined;——
closeOnEscapecloseOnEscape?: boolean | undefined;——
descriptiondescription?: string | undefined;——
initialFocusinitialFocus?: string | false | (() => HTMLElement | null) | undefined;——
onEscapeKeyDownonEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;——
onInteractOutsideonInteractOutside?: ((event: Event) => void) | undefined;——
onPointerDownOutsideonPointerDownOutside?: ((event: PointerEvent) => void) | undefined;——
overlayPropsoverlayProps?: DialogOverlayProps | undefined;——
titletitle: string;——

CommandPaletteLinkProps

Import from @askrjs/themes/command.

PropTypeDefaultDescription
closeOnSelectcloseOnSelect?: boolean | undefined;——
onBeforeNavigateonBeforeNavigate?: ((event: Event) => void) | undefined;——

CommandPaletteListProps

Import from @askrjs/themes/command.

PropTypeDefaultDescription
childrenchildren?: unknown;——
refref?: Ref<HTMLUListElement>;——

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.