Components / Controls
Combobox
A text input with a list of suggestions. People type to narrow the list, then pick with the arrow keys and Enter or with a click. Options can come from a server as they type.
When to useLink to "When to use"
- A long list where typing is faster than scrolling: countries, fonts, tables, people.
- Results from a server as people type.
- Free text with suggestions (
allowCustom): tags, labels.
Use something else when:
- there are only a handful of options and no need to type: Select
- people search for commands or places to go: the CommandPalette
- the text is free and needs no suggestions: TextField
UsageLink to "Usage"
import { Combobox } from "@arshad-shah/cynosure";
<Combobox label="Fruit" options={fruits} name="fruit" required />By default an option matches when its label contains the typed text, ignoring case. Pass filter to match your way. While people type, the text is marked where it appears in each label (HighlightedText); options are still named by their whole label.
Options from a serverLink to "Options from a server"
Control the text with inputValue and onInputChange, fetch, and pass the results as options with filter={false}. While loading, the list says so. Focus never leaves the input, so results arriving late never swallow keystrokes; the first enabled result becomes active.
const [query, setQuery] = useState("");
const { data, isLoading } = useSearch(query);
<Combobox
label="User"
options={data}
inputValue={query}
onInputChange={setQuery}
filter={false}
loading={isLoading}
/>Trailing text, dimmed options and a footer actionLink to "Trailing text, dimmed options and a footer action"
An option's trailing is drawn at the end of its row, smaller and muted (a shortcut, a count). dimmed draws an option muted while it stays choosable. footer pins an action under the options, { label, icon?, onSelect }, whatever the text matches: it is the last stop of the arrow keys, and Enter or a press closes the list and runs it. Focus stays in the input and the value does not change.
Coloured iconsLink to "Coloured icons"
iconTone and iconColor colour an option's icon and mean what Icon's tone and color mean: iconTone is a semantic colour (accent, neutral, danger, success, warning, info, muted), iconColor is any CSS colour and overrides it (brand draws a brand mark in its owner's colour). The active and the selected option keep the colour. A disabled option shows its icon without the colour, muted with the rest of the row. The input itself shows text only: iconStart is the field's own icon.
PropsLink to "Props"
| Prop | What it does | Type | Default |
|---|---|---|---|
labelRequired | The field's label. It also names the list when it is a string. | ReactNode | |
optionsRequired | The options to choose from. | ComboboxOption[] | |
labelHidden | Visually hide the label (it still names the control). Prefer visible labels. | boolean | |
description | Help text shown below the control and read with it. | ReactNode | |
error | Your own error; it replaces the field's own messages. | ReactNode | |
footer | An action pinned under the options ("New connection"), shown whatever the text matches: the arrow keys' last stop, run with Enter or a press. The list closes, focus stays in the input, and the value does not change. | OptionListAction | |
value | The chosen option's value (or the typed text, with allowCustom). | string | |
defaultValue | The value chosen at first, when uncontrolled. | string | |
onChange | Called when the value changes, with the chosen option's value, or an empty string when it is cleared. | ((value: string) => void) | |
inputValue | The text in the input. Control it to load options as people type. | string | |
onInputChange | Called when the text in the input changes (typed, or filled in by a choice), with the text. | ((text: string) => void) | |
filter | Which options match the text. Default: label contains the text, ignoring case. false: show options as given. | false | ((option: ComboboxOption, text: string) => boolean) | label contains the text |
allowCustom | Accept text that matches no option as the value. | boolean | |
loading | Options are being fetched: the list says so and is aria-busy. | boolean | |
placeholder | Hint shown in the input while it is empty. | string | |
name | Name the value is submitted under in a form. | string | |
required | A value must be chosen: submitting the form without one is blocked and shows an error. | boolean | |
disabled | Turns off the input; the value is not submitted with a form. | boolean | |
size | Size of the field. Default "md". | Size | "md" |
variant | outline or soft (tinted, borderless until focus). Default "outline". | "soft" | "outline" | "outline" |
iconStart | Icon at the start of the input. | IconData | |
labels | Replace the built-in English text: the empty and loading notes and the required error. | Partial<ComboboxLabels> | |
className | Added to the root element, for layout. | string | |
style | Layout only. | CSSProperties | |
layout | stack puts the label above the control and the description and error below it. split puts the label and description at the start and the control at the end of one row (a settings row); when the field is too narrow for both, the control moves under the text. Default "stack". | "stack" | "split" | "stack" |
width | Width of the control, so the controls of a column of fields line up: "sm", "md" and "lg" are the --cy-field-control-width-* tokens (never wider than the field), "full" is the whole field. Default: the control's own width (the whole field in the stacked layout for TextField and the other fields). | FieldWidth |
Generated from the type definitions in @arshad-shah/cynosure 0.5.0.
Behaviour and accessibilityLink to "Behaviour and accessibility"
| Input | Result |
|---|---|
| Typing | Filters and opens the list; the first match is active |
| Down arrow / Up arrow | Opens on the first / last option, then moves (disabled options are skipped) |
| Enter | Chooses the active option, or runs the active footer action (with allowCustom and no active option, keeps the text) |
| Escape | Closes the list; pressed again, clears the text and the value |
| Tab or a click elsewhere | Closes the list and settles the value |
- Roles: the input is
role="combobox"witharia-expanded,aria-controls,aria-autocompleteandaria-activedescendant; the popup is alistboxofoptions. - Leaving the field: text that matches no option goes back to the last choice (unless
allowCustom); an empty field clears the value. - Forms: with
name, the chosen value is submitted. Withrequired, a blocked submit focuses the input and showslabels.required. Reset restores the default. - Layers: the list is in the top layer, so it works inside a Dialog. Escape closes one thing at a time: the list, then the text, then the dialog.
TouchLink to "Touch"
Option rows are at least 44px tall on coarse pointers.
ThemingLink to "Theming"
Tokens: --cy-combobox-list-max-height, --cy-combobox-list-max-width, --cy-combobox-list-bg and --cy-combobox-option-active-bg. The input uses the TextField tokens. The list is an OptionList: these tokens set its --cy-option-list-* tokens.
RelatedLink to "Related"
Select · TextField · OptionList · SearchField
These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.