Overview
Reference usage
Filterable dropdown that combines a text input with a selectable option list.
Usage
Grouped options
Give options a group name to render them under headings. Ungrouped options come first without a heading, and groups follow in order of first appearance, even when the groups interleave in options. Each heading shows the group name and how many of its options are listed. Typing filters across every group, keeps the headings of groups that still match, and hides the rest; arrow keys move through the options in the order they are displayed.
The default filter matches an option's label and description, not its group name. maxVisibleOptions counts options in display order.
When to use
- Choosing one value from a long list where typing is faster than scrolling.
- Letting users narrow options by substring while still requiring a constrained selection.
- Picking from a short fixed list with no need to filter — use select instead.
- Querying remote data or accepting free-text submissions — use search-field instead.
Examples
Basic combobox
Type to filter; the list is filtered with a case-insensitive substring match.
Disabled combobox
Disabled combobox cannot be focused or edited.
Grouped options
Give options a group to render them under headings with counts. Typing filters across groups and keeps the headings of groups that still match.
Typed options with as const
Use `as const` on the options array to infer a precise literal-union type for `T`. TypeScript then rejects any `value` that is not a member of the union (or the empty-string sentinel) at compile time.
Props
Name | Type | Default | Description |
|---|---|---|---|
id required | text | Unique identifier — required for label association and ARIA wiring. | |
value bindable | AllowCustom extends true ? string : NoInfer<T>'' | '' | Currently selected value. Bindable. '' when nothing is selected. |
onValueChange | (value: AllowCustom extends true ? string : T) => void | Called when an option, or an arbitrary value when enabled, is committed. | |
name | text | Native form field name. Renders a hidden input carrying the selected value. | |
textInputValue bindable | text | '' | Free-text input value (the text the user has typed). Bindable. |
options required | ComboboxOption<T>[] | Full set of options to filter. The sole inference source for T. | |
label | text | Visible label rendered in a <label> associated via for. | |
placeholder | text | Placeholder when no value is selected. | |
filter | (option: ComboboxOption<T>, query: string) => boolean | Custom synchronous filter. Receives an option and the current input value; returns true to keep. Defaults to case-insensitive substring match on label. | |
description | text | Helper text displayed below the input; wired via aria-describedby. | |
error | text | Validation error message; sets aria-invalid="true". | |
disabled | boolean | Disables the combobox. Inherited from a wrapping FormField when unset. | |
required | boolean | Marks the field required: renders the required marker on the label and
sets aria-required on the input. Inherited from a wrapping FormField
when unset. | |
maxVisibleOptions | number | 200 | Hard cap on visible filtered options. Default 200. |
customValueAllowed | AllowCustom | Allow committing typed text that is not present in options. | |
size | 'sm' | 'md' | 'lg' | 'md' | Height step from the shared --cinder-control-height-* scale: sm 28px, md 32px,
lg 40px, the same heights as a Button of that size. |
sheetBelow | text | Viewport width below which the options panel docks to the bottom edge as
a sheet (Popover's sheetBelow, with focus kept in the input), instead of
anchoring to the input. A simple CSS length such as '640px', or false
to always anchor. Default '640px'. |