Combobox

Searchable single-choice field with filtered options.

Overview

  • Use Combobox when typing helps users find an option within a moderate list.

Aliases

autocomplete, filterable select

When to use

  • Use Combobox when the option set is long enough that filtering is faster than scanning.
  • Use it when people may know part of the label but not the exact final option.

When not to use

  • Use Select when users can scan the options without filtering.
  • Do not use it for async search or multi-select.

Structural parts

field wrapper

root

Provides label, description, and shell treatment.

combobox input

input

Receives the typed filter text and current selection label.

anchored options surface

listbox

Shows the filtered option set.

list option

option

Selectable option row with label and optional description.

Public interface

Props
NameTypeDefaultDescription
labelstring—Visible label used for the field or control.
descriptionstring—Provides field guidance associated with the control.
errorstring—Shows a validation error associated with the control.
placeholderstring—Placeholder text shown before a user makes a selection or enters text.
requiredbooleanfalseMarks the control as required.
disabledbooleanfalsePrevents interaction and exposes the disabled state.
namestring—Form field name used for native form submission.
idstring—Sets the control ID for external labels and descriptions.
size'sm' | 'md' | 'lg''md'Sets the component size.
itemsArray<{ value: string; label: string; description?: string; disabled?: boolean }>—Available options rendered inside the listbox.
valuestring—Controlled selected value.
onChange(detail: { value: string | undefined }) => void—Runs when a selection is committed.
themeThemeContract—Sets the theme used to resolve component styles.
Events
NamePayloadDescription
change{ value: string | undefined }Fires when the component commits a new value.
Slots
NameDescription
defaultCombobox is data-driven and does not expose option slots.

Variants, sizes, and states

Variants

  • default: Combobox uses one searchable shell and varies by size.

Sizes

  • sm: Compact searchable field.
  • md: Default searchable field.
  • lg: Larger searchable field.

States

  • closed: Input focused or idle without the list surface visible.
  • open: Anchored listbox is visible.
  • highlighted: One option is active for keyboard navigation.
  • selected: A value has been committed into the field.

Accessibility

Semantics

  • Associates the control with its visible label, description, and error.
  • Exposes disabled and required semantics through the underlying form control.
  • Uses combobox and listbox semantics through the searchable input and anchored option surface.

Keyboard

  • Supports native focus and text entry behavior.
  • Arrow keys move through options when the listbox is open.
  • Enter commits the highlighted option and Escape closes the listbox.

Screen readers

  • Connects visible label, helper text, and error text to the native control.
  • The input exposes its value, associated listbox, and active option.

Checklist

  • Verify that the control has an accessible name.
  • Verify that keyboard focus is visible in every state and size.
  • Identify disabled, selected, and error states with text or symbols as well as color.

Tokens and CSS variables

root

--dk-field-stack-gap
0.45rem
--dk-motion-duration
200ms
--dk-combobox-offset
8px

label

--dk-field-label-color
#16181c
--dk-field-label-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-field-label-weight
600

input

--dk-combobox-input-bg
#f2f5fb
--dk-combobox-input-fg
#16181c
--dk-combobox-input-border
#95989d
--dk-combobox-input-block-size
48px
--dk-combobox-input-inline-padding
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-combobox-input-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-combobox-input-font-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)

icon

--dk-combobox-icon-size
1rem
--dk-combobox-icon-color
#16181c

description

--dk-field-description-color
#16181c
--dk-field-description-size
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

error

--dk-field-error-color
#cc272e
--dk-field-error-size
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

surface

--dk-combobox-surface-bg
#f2f5fb
--dk-combobox-surface-fg
#16181c
--dk-combobox-surface-border
#95989d
--dk-combobox-surface-radius
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-combobox-surface-shadow
0 10px 15px rgba(0, 0, 0, 0.06), 0 4px 6px rgba(0, 0, 0, 0.04)
--dk-combobox-surface-width
320px
--dk-combobox-surface-padding
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

item

--dk-combobox-item-bg
transparent
--dk-combobox-item-fg
#16181c
--dk-combobox-item-radius
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
--dk-combobox-item-min-height
44px
--dk-combobox-item-inline-padding
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)

itemLabel

--dk-combobox-item-label-size
clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
--dk-combobox-item-label-weight
550

itemDescription

--dk-combobox-item-description-size
clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)

Implementation notes

  • Combobox supports one value and local filtering. It does not provide asynchronous search or freeform entry.

Examples

Starter

Searchable preset picker

A searchable field for moderate preset lists.

<Combobox label="Choose a system" description="Filter by name." items={systems} />

Common patterns

Compact tool picker

Smaller size works well in dense operational tools.

<Combobox size="sm" label="Preset" placeholder="Find preset" items={systems} />

Edge cases

Controlled selection

Control the selected value when the surrounding app owns the state.

<Combobox label="Preset" items={systems} value={selectedPreset} onChange={(detail) => selectedPreset = detail.value} />

Mathematical fixtures

Calculated fixtures; browser evidence is not collected. Layout estimates use declared text behavior and maximum token values.

default (size=sm)

pass

size=sm

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 44 px
  • Rows: 44 px
  • Surface: 320 × 280 px

default (size=md)

pass

size=md

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 48 px
  • Rows: 44 px
  • Surface: 320 × 280 px

default (size=lg)

pass

size=lg

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 52 px
  • Rows: 44 px
  • Surface: 320 × 280 px

selected (size=sm)

pass

size=sm

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 44 px
  • Rows: 44 px
  • Surface: 320 × 280 px

selected (size=md)

pass

size=md

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 48 px
  • Rows: 44 px
  • Surface: 320 × 280 px

selected (size=lg)

pass

size=lg

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 52 px
  • Rows: 44 px
  • Surface: 320 × 280 px

invalid (size=sm)

pass

size=sm

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 44 px
  • Rows: 44 px
  • Surface: 320 × 280 px

invalid (size=md)

pass

size=md

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 48 px
  • Rows: 44 px
  • Surface: 320 × 280 px

invalid (size=lg)

pass

size=lg

  • Evidence: mathematical
  • Coverage: complete (4 / 4 declared kinds evaluated)
  • Declared: contrast, target, optionRow, anchoredSurface
  • Evaluated: contrast, target, optionRow, anchoredSurface
  • Contrast: 98.5 Lc
  • Target: 52 px
  • Rows: 44 px
  • Surface: 320 × 280 px