Skip to content
Cynosurev0.5.0
SearchStorybookGitHubnpmColour mode: System. Switch to Light

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.

Type to filter then choose with enter

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"

tsx
Copy
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.

Async results arrive late without losing keys
tsx
Copy
const [query, setQuery] = useState("");
const { data, isLoading } = useSearch(query);

<Combobox
  label="User"
  options={data}
  inputValue={query}
  onInputChange={setQuery}
  filter={false}
  loading={isLoading}
/>

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.

Trailing dimmed and afooter action

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.

Option icons keep their colour

PropsLink to "Props"

Every prop of Combobox
PropWhat it doesTypeDefault
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"

Behaviour and accessibility, table 1
InputResult
TypingFilters and opens the list; the first match is active
Down arrow / Up arrowOpens on the first / last option, then moves (disabled options are skipped)
EnterChooses the active option, or runs the active footer action (with allowCustom and no active option, keeps the text)
EscapeCloses the list; pressed again, clears the text and the value
Tab or a click elsewhereCloses the list and settles the value
  • Roles: the input is role="combobox" with aria-expanded, aria-controls, aria-autocomplete and aria-activedescendant; the popup is a listbox of options.
  • 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. With required, a blocked submit focuses the input and shows labels.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.
Inside adialog escape closes one thing at atime

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.

Select · TextField · OptionList · SearchField

These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.

Getting started
Theming
Icons
Accessibility
Code editors and highlighters
Using Cynosure without React
Build-tool adapters
Components
Accordion
AppShell
AspectRatio
Breadcrumbs
Calendar
Card
Container
Disclosure
Divider
DocumentViewport
Grid
Inline
PageHeader
PanZoomCanvas
ScrollArea
SideNav
SortableList
SplitPane
Stack
StatusBar
Tabs
TitleBar
Toolbar
Tree
VirtualList
ZoomControls
Announcer
Avatar
Badge
CodeBlock
DescriptionList
EmptyState
ErrorBoundary
Field
Heading
IconTile
Image
Kbd
List
LoadingDots
Notice
ProgressBar
Prose
Skeleton
Stat
Steps
Table
Text
Button
Checkbox
Checklist
ColorField
ColorSwatches
Combobox
CompareSlider
CopyButton
DateField
FileDrop
IconButton
KeyValueEditor
Link
NumberField
Pagination
PathField
RadioGroup
SearchField
SegmentedControl
Select
SelectionFrame
SignaturePad
Slider
Switch
TagInput
TextArea
TextField
ThemeToggle
TimeField
ButtonBase
ChoiceBase
DialogBase
FileInputBase
HiddenValue
Icon
InputBase
LinkBase
LiveRegion
TextAreaBase
ChatMessage
Choice
DataGrid
DeviceFrame
HighlightedText
HotkeyField
ListRow
OptionList
OverlayFrame
QRCode
RowActions
Section
SiteFooter
SiteHeader
SkipLink
SortButton
VisuallyHidden
CommandPalette
ContextMenu
Dialog
FloatingToolbar
HoverCard
Menu
Menubar
Popover
ProgressOverlay
Sheet
Toast
Tooltip
Changelog