Pular para o conteúdo

Combobox (typeahead select)

components specs/components/combobox.kmd

Typeahead input + dropdown of filtered options with optional async loading, custom-value support, and multi-select variant. Replaces ad-hoc native `<select>` + JS combinations that vary in a11y across Koder products. Modeled after Duet, Polaris, Spectrum.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Component — Combobox

Status: v0.1.0 — Draft.

R1 — Anatomy

  • Input cell: text input + trailing caret icon + optional leading icon.
  • Dropdown popover: option list anchored to input; opens below by default, flips above if no space.
  • Each option: leading icon (optional) + label + secondary text (optional) + trailing checkmark (selected state in multi-mode).

R2 — Behaviors

BehaviorDefaultConfigurable
Typeahead filtersubstring match on labelfull-text matcher overridable
Async option loadoffcallback returning Promise<Option[]>
Free-text custom valueofftoggle to accept user-typed values not in list
Multi-selectofftoggle; selected values render as chips in input cell
Group separatorsnoneoptions may carry group field, renders sticky group heading

R3 — ARIA semantics

  • Container: role="combobox" with aria-expanded, aria-controls (pointing at listbox), aria-autocomplete="list".
  • Listbox: role="listbox" with each option role="option"; aria-selected reflects selection.
  • Multi mode: listbox aria-multiselectable="true".
  • Active descendant: aria-activedescendant points at the visually-highlighted option during keyboard nav.

R4 — Keyboard

KeyAction
Open dropdown (if closed); highlight next option
Highlight previous option
EnterSelect highlighted option; in custom-value mode and no match, commit input value as value
TabCommit selection + move focus out
EscClose dropdown without changing selection
Backspace (in multi, empty input)Remove the last chip
Home / EndHighlight first / last option
TypeFilters list; highlights first match

R5 — States

  • Loading (async): spinner inside dropdown; live-region announces "Loading options".
  • No results: empty-state-style cell inside dropdown ("No matches"); if custom value allowed, hint to "Press Enter to add".
  • Error: dropdown shows red message with retry button.
  • Disabled: input + caret muted, typing blocked, keyboard ignored.

R6 — i18n

  • All UI strings (placeholder, "Loading", "No matches", "Add custom") translatable per specs/i18n/contract.kmd.
  • Option labels rendered as-is from data; locale formatting is the consumer's responsibility.

R7 — OUIA

Per specs/testing/ouia-test-hooks.kmd:

  • data-ouia-component-type="Combobox"
  • data-ouia-safe="true" only when no pending async load and no open popover.

Não-escopo

  • Virtualized option list for huge option counts (separate ticket if pursued).
  • Tag-input mode (free-form chips without dropdown) — that's a different primitive.

Referências