Skip to main content

Completed Design-System API Review

Scenario

The design-system team proposes a new Combobox primitive used by search, filters, assignment workflows, and GenUI-generated forms. The component must support keyboard navigation, async results, multi-select, grouped options, validation, virtualization, and theming.

Decision

Approve the component as a headless primitive plus styled product wrappers. Do not expose a single prop-heavy component for all use cases. Require an accessibility contract, state model, async loading contract, and migration plan before broad adoption.

API boundary

@atlas/ui-primitives/combobox
-> behavior, keyboard, ARIA, state machine, test fixtures

@atlas/design-system/combobox
-> tokens, visual states, density, theming, icons

product wrappers
-> CustomerCombobox, UserAssignCombobox, ReportFilterCombobox

Reviewed API shape

Required stable concepts:

  • value
  • inputValue
  • options
  • selectedOptions
  • loading
  • disabled
  • invalid
  • onInputChange
  • onSelectionChange
  • getOptionKey
  • getOptionLabel
  • renderOption
  • emptyState
  • loadingState
  • errorState

Rejected API choices:

ProposalReason rejected
any[] options with implicit label fieldbrittle across product domains
built-in data fetchingcouples primitive to app data layer
visual-only invalid stateinaccessible error handling
automatic virtualization always onunnecessary complexity for small lists
generic metadata propencourages hidden product behavior inside primitive

Accessibility contract

The component must define:

  • label and accessible name requirements
  • keyboard behavior for open, close, navigate, select, clear, and escape
  • focus behavior after selection and validation errors
  • screen-reader announcement for result count, loading, empty, and error states
  • disabled and read-only behavior
  • reduced-motion behavior
  • touch target expectations
  • form integration and error description mapping

State model

Test matrix

TestRequired
keyboard open/navigate/select/escapeyes
label and error descriptionyes
async loading and stale response orderingyes
empty stateyes
grouped optionsyes
multi-select chipsyes
virtualization with keyboard navigationyes for large list wrapper
high contrast and forced colorsyes
reduced motionyes
screen-reader smoke testmanual before stable release

Versioning policy

  • primitive starts at 0.x for two product pilots
  • stable 1.0 requires two successful adoptions and no critical accessibility defects
  • breaking API changes require migration guide and codemod where possible
  • product wrappers can evolve faster than primitive behavior

Adoption plan

  1. Pilot in report filters and user assignment.
  2. Collect defects, unsupported states, and API friction.
  3. Stabilize primitive behavior and visual wrapper separately.
  4. Migrate legacy select/search components by workflow priority.
  5. Add design-system docs with do/don't examples.
  6. Mark old components deprecated with removal date.

Approval criteria

  • headless primitive and styled wrapper boundaries are clear
  • accessibility contract is documented and tested
  • async behavior does not own product data fetching
  • product wrappers own domain-specific rendering
  • migration plan exists for legacy select/search components
  • component is compatible with GenUI registry only through validated props

Source lens

This review is grounded in Part VII design-system architecture, accessibility contracts, the enterprise design-system solution pack, and GenUI registry constraints from Part XIII.