Forms · astro-ui · Combobox

ComboboxJS

Select-style trigger that opens a searchable listbox — pick one from many.

Combobox reads like a select: the trigger shows the committed value with a chevron, and opening it reveals a panel with a search field on top of a filterable listbox. Type to filter (case-insensitive substring on label/value), move with ↑/↓, commit with Enter or click, dismiss with Escape. The committed value posts with the form via a hidden input under the field’s name. The selected option carries a check mark, and options can carry a muted hint line. With JS disabled the trigger still renders the committed value; the popup and search need the small scoped script.

Features

  • Select-style trigger (committed value + chevron) with a search field inside the popup
  • Case-insensitive substring filtering across label and value
  • Full keyboard support: ↑/↓ navigate, Enter commits, Escape closes, Home/End jump
  • Check mark on the committed option; autoHighlight to land on the first match
  • Grouped options with labelled sections, per-option hints
  • Five sizes and eight border variants matching Input; clearable button
  • Committed value posts with the form via a hidden input under name

Usage

---
import { Combobox } from "astro-ui";
---

<Combobox
  name="framework"
  placeholder="Select framework…"
  items={["Astro", "Next.js", "Nuxt", "SvelteKit"]}
  clearable
/>

Demos

Basic

<Combobox
  name="framework"
  placeholder="Select framework…"
  items={["Astro", "Next.js", "Nuxt", "SvelteKit", "Remix"]}
/>

Preselected + clearable

<Combobox
  name="country"
  value="jp-tokyo"
  clearable
  placeholder="Choose a city…"
  items={[
    { value: "jp-tokyo", label: "Tokyo", hint: "Japan" },
    { value: "fr-paris", label: "Paris", hint: "France" },
    { value: "us-nyc", label: "New York", hint: "United States" },
  ]}
/>

Groups

<Combobox
  name="stack"
  placeholder="Search the stack…"
  groups={[{ label: "Frontend", items: ["Astro", "Next.js", "Nuxt"] }, { label: "Backend", items: ["Node", "Deno", "Bun"] }]}
/>

Sizes

<Combobox size="xs" items={…} placeholder="xs" />
<Combobox size="sm" items={…} placeholder="sm" />
<Combobox size="md" items={…} placeholder="md" />
<Combobox size="lg" items={…} placeholder="lg" />

Invalid & disabled

<Combobox invalid placeholder="Required field…" items={["One", "Two", "Three"]} />
<Combobox disabled placeholder="Disabled" items={["One", "Two"]} />

API

Props

PropTypeDefaultDescription
items(string | { value, label, hint? })[][]Option list; strings become both value and label.
groups{ label, items }[]—Labelled sections; overrides items when set.
namestring—Form field name; committed value posts via a hidden input.
valuestring—Initial committed value (server-side preselect).
placeholderstring"Select…"Trigger text when nothing is committed.
searchPlaceholderstring"Search…"Placeholder for the search field inside the popup.
emptyMessagestring"No results found."Shown when the filter matches nothing.
autoHighlightbooleanfalseHighlight the first match when filtering.
clearablebooleanfalseRender a clear (✕) button on the trigger when a value is committed.
size"xs" | "sm" | "md" | "lg" | "xl""md"Trigger size (heights mirror Input).
variant"inherit" | "primary" | … | "info""inherit"Border color variant (mirrors Input).
placement"bottom" | "top""bottom"Which side the panel opens on.
panelWidthstringtrigger widthFixed panel width (any CSS inline-size value).
disabled / required / invalidbooleanfalseNative states + invalid styling hook.
classstring—Merged via cn(); Tailwind classes welcome.
idstring—Element id.

Accessibility

Implemented accessibility features — semantics, ARIA wiring, and keyboard behavior that ship with the component.

  • Trigger carries role=combobox with aria-expanded and aria-controls pointing at the listbox
  • In-popup search filters the listbox and manages aria-activedescendant
  • Options carry role=option and aria-selected state managed by the script
  • Groups use role=group with accessible labels
  • Escape always returns focus to the trigger; Tab closes without stealing focus

FAQ

How is this different from Autocomplete?

Autocomplete is a typable text input that suggests completions; the value can be typed freely. Combobox is a select-style trigger — the value can only come from the list, but a search field inside the popup makes long option sets findable. Use Combobox when the value must be one of the options.

Does it work without JavaScript?

The trigger renders server-side with the committed value and posts it with the form via a hidden input. Opening the popup, searching, and keyboard selection need the small scoped script that ships with the component.

Changelog

Version history mentioning Combobox.

v0.1.0 — 2026-11-11
added
  • Forms (18): Autocomplete, Combobox, Label, Field, Input, InputGroup, Textarea, Select, Checkbox, Radio, Switch, Toggle, ToggleGroup, RadioGroup, Rating, Slider, DatePicker, TimePicker.
  • Native-first interactive behavior: Dialog, AlertDialog, and Sheet on <dialog>; Accordion and Collapsible on <details>; Tabs, Menu, Tree, and Combobox with WAI-ARIA roles and scoped keyboard scripts.