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
No results found.
<Combobox
name="framework"
placeholder="Select framework…"
items={["Astro", "Next.js", "Nuxt", "SvelteKit", "Remix"]}
/>Preselected + clearable
No results found.
<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
Frontend
Backend
No results found.
<Combobox
name="stack"
placeholder="Search the stack…"
groups={[{ label: "Frontend", items: ["Astro", "Next.js", "Nuxt"] }, { label: "Backend", items: ["Node", "Deno", "Bun"] }]}
/>Sizes
No results found.
No results found.
No results found.
No results found.
<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
No results found.
No results found.
<Combobox invalid placeholder="Required field…" items={["One", "Two", "Three"]} />
<Combobox disabled placeholder="Disabled" items={["One", "Two"]} />API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | (string | { value, label, hint? })[] | [] | Option list; strings become both value and label. |
groups | { label, items }[] | — | Labelled sections; overrides items when set. |
name | string | — | Form field name; committed value posts via a hidden input. |
value | string | — | Initial committed value (server-side preselect). |
placeholder | string | "Select…" | Trigger text when nothing is committed. |
searchPlaceholder | string | "Search…" | Placeholder for the search field inside the popup. |
emptyMessage | string | "No results found." | Shown when the filter matches nothing. |
autoHighlight | boolean | false | Highlight the first match when filtering. |
clearable | boolean | false | Render 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. |
panelWidth | string | trigger width | Fixed panel width (any CSS inline-size value). |
disabled / required / invalid | boolean | false | Native states + invalid styling hook. |
class | string | — | Merged via cn(); Tailwind classes welcome. |
id | string | — | 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.
- 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.