Combobox
Forms & choicesBrick 0.1.2

Combobox

Combobox is Brick's finished searchable single-value choice control. Atom owns filtering, keyboard focus, selection, open state, collision-aware positioning, dismissal, ARIA, and optional free text; Brick owns its visual system.

Live example

Built from the published package

Interactive
Choose with confidence

Know when Combobox is the right part

Use it when

Use Combobox when a predefined option set benefits from filtering. Enable freeSolo only when values outside that set are valid.

Choose another path when

Use Select for select-only choices, Input for unconstrained text, Multi Select for several values, and menus for actions.

Installation and imports

tsx
import { Combobox } from "@flowstack-ui/brick/combobox";
import { Field } from "@flowstack-ui/brick/field";
import "@flowstack-ui/brick/styles.css";

The complete stylesheet above is the recommended default. For a measured route-aware build, replace it with the shared foundation and this component's stylesheet:

tsx
import "@flowstack-ui/brick/styles/core.css"; // once at the application root
import "@flowstack-ui/brick/styles/combobox.css";

Add the modular stylesheet for every other Brick component the route renders. Do not combine modular styles with styles.css or tokens.css.

Quick start

tsx
<Field.Root id="city">
  <Field.Label>City</Field.Label>
  <Combobox.Root options={cities}>
  <Combobox.Control><Combobox.Input placeholder="Search cities" /><Combobox.Clear aria-label="Clear city" /><Combobox.Trigger aria-label="Toggle city options" /></Combobox.Control>
  <Combobox.Portal><Combobox.Content><Combobox.Listbox>
    {cities.map(city => <Combobox.Item key={city.value} label={city.label} value={city.value}>{city.label}</Combobox.Item>)}
    <Combobox.Empty>No matching cities</Combobox.Empty>
  </Combobox.Listbox></Combobox.Content></Combobox.Portal>
  </Combobox.Root>
  <Field.Error>Choose a city.</Field.Error>
</Field.Root>

Visual recipes and states

Recipes change paint and geometry only. Controls and option rows use matching 36/44/52px sm/md/lg minimums. Atom attributes drive open, highlighted, selected, disabled, read-only, empty, and loading presentation. Content is viewport-bounded; options reserve a selected-indicator column.

Examples

tsx
<Combobox.Root freeSolo options={cities}>
  <Combobox.Label>Destination</Combobox.Label>
  <Combobox.Control><Combobox.Input /><Combobox.Clear aria-label="Clear destination" /></Combobox.Control>
</Combobox.Root>
Public contract

API

Start with the public parts and root options below. Components with multiple parts separate each area into its own named subsection.

PropValuesDefault
variantoutline, soft, underlineoutline
sizesm, md, lgmd
shapesharp, rounded, pillrounded
fullWidthbooleantrue

Underline has fixed sharp geometry. Root forwards Atom's value, input, open, filtering, option, disabled/read-only, loading, and freeSolo APIs. Recipe types are ComboboxVariant, ComboboxSize, and ComboboxShape.

Named exports are Combobox, ComboboxRoot, ComboboxLabel, ComboboxControl, ComboboxInput, ComboboxClear, ComboboxTrigger, ComboboxIndicator, ComboboxPortal, ComboboxContent, ComboboxListbox, ComboboxGroup, ComboboxItem, ComboboxEmpty, and ComboboxLoading. Their prop types are ComboboxRootProps, ComboboxLabelProps, ComboboxControlProps, ComboboxInputProps, ComboboxClearProps, ComboboxTriggerProps, ComboboxIndicatorProps, ComboboxPortalProps, ComboboxContentProps, ComboboxListboxProps, ComboboxGroupProps, ComboboxItemProps, ComboboxEmptyProps, and ComboboxLoadingProps.

Shared responsibility

Accessibility

Use Field.Root, Field.Label, Field.Description, and Field.Error for ordinary form spacing and error relationships. Combobox also works standalone with Combobox.Label and Root's invalid, disabled, readOnly, and required props. Atom owns combobox/listbox/option roles, active descendant, keyboard navigation, filtering, selection, disclosure, forms, and dismissal. Touch outside dismissal waits for release, so dragging or scrolling does not become a tap. Artwork is decorative. Options must not contain interactive descendants.

Responsive behavior

The control uses logical spacing and full width by default. Content remains collision-aware, viewport-bounded, scrollable, and reachable in narrow, zoomed, keyboard-open, and RTL layouts.

Stable visual contract

Styling and tokens

Customization

Use recipes first, then scoped variables: <Combobox.Control style={{ "--brick-combobox-border": "var(--brick-color-accent-border)" }} />.

Tokens and CSS hooks

Public variables are --brick-combobox-min-block-size, --brick-combobox-padding-inline, --brick-combobox-radius, --brick-combobox-background, --brick-combobox-border, --brick-combobox-foreground, --brick-combobox-placeholder, --brick-combobox-focus, --brick-combobox-invalid, and --brick-combobox-popup-radius. Stable .brick-combobox-* classes and data-slot hooks cover DOM parts.

Control exposes data-full-width, data-shape, data-size, and data-variant. Content exposes the inherited data-size; both retain overridable data-slot.

Advanced reference

Open these details only when you need to inspect DOM ownership, native forwarding, or lower-level composition.

Maintainer resources

Tests, playground evidence, source notes, and release history remain available without crowding the plug-and-play guide.