@ai-created/ui
All components

Fields & selection

Dropdown

An accessible controlled listbox for choosing one option in compact space.

DropdownDropdownPropsDropdownOption
View source

Component workbench

Configure the production component, inspect it at responsive widths, copy synchronized JSX, and share the exact state from one workspace.

Sort by

Anatomy

Named regions define what belongs to the component, what remains optional, and where semantic responsibility lives.

1

Listbox root

Required

Headless UI state and semantic owner.

2

Label

Required

Persistent visible listbox name.

3

Trigger

Required

Current selection or placeholder and disclosure icon.

button
4

Options panel

Required

Anchored, scrollable list of values.

5

Option

Required

Selectable row with optional check marker and disabled state.

Construction and authoring

The Figma-equivalent asset model, auto-layout, resizing, properties, slots, content bounds, localization, and governance contract.

Asset kind

component

Design library name

Components/Forms/Dropdown

Maturity

stable

Last reviewed

2026-08-29

Canvas applicability

Publish closed and open variants with nested option instances and selected state.

Auto layout

Direction
vertical
Gap
8px label gap; 4px trigger to menu
Padding
0px
Alignment
Stretch
Wrap
Menu options do not wrap by default

Resizing

Width
fill
Height
hug
Minimum width
200px
Maximum width
Parent controlled
Minimum height
44px closed
Maximum height
Menu maximum 240px plus trigger
Overflow
visible
  • Menu width matches the trigger and scrolls after its maximum height.

Exposed design properties

PropertyTypeDefaultCode mappingOptions or notes
LabelRequiredtextSelect optionlabelNo additional constraint
Selected valueRequiredvariantNonevalueNo additional constraint
PlaceholdertextSelect an optionplaceholderNo additional constraint
DisabledbooleanfalsedisabledNo additional constraint
Open previewbooleanfalseInternal Headless UI state; no public propNo additional constraint
OptionsRequiredslotNoneoptionsNo additional constraint

Nested assets and slots

Listbox label

primitive / required

Accessible field label.

ListboxLabel

Trigger

subcomponent / required

Current value and chevron button.

ListboxButton

Options panel

subcomponent / required

Anchored, scrollable menu.

ListboxOptions

Option

subcomponent / required

Repeatable selected, active, or disabled row.

DropdownOption data item

Content limits

Options

Recommended two to fifteen options

Overflow: Use search or autocomplete for larger datasets.

A long unfiltered list is inefficient.

Option label

One line, recommended maximum 40 characters

Overflow: Truncate visually only when the full value is otherwise available.

Menu scanning depends on concise parallel labels.

Localization and RTL

Translatable: Label, Placeholder, Option labels

  • Text and chevron align to logical sides.
  • Menu anchors to logical start.
  • Test longest option.
  • Test a translated placeholder.
  • Test keyboard navigation in right-to-left mode.

Responsive behavior

Trigger fills its form column; menu matches trigger width.

No internal breakpoint

  • Keep the menu inside the viewport.
  • Use a full-screen selection pattern only in a product-level mobile adaptation.

Authoring limits

  • Figma open state does not validate focus movement, collision handling, or scrolling.
  • Options use stable untranslated values and localized labels.

Accountable owner

Design systems form foundations owner

Canonical source: src/components/Dropdown.tsx

  • Selection behavior changes require Headless UI parity and keyboard testing.
  • A breaking property, token, or behavior change requires design and engineering approval, a migration note, and a major release.
  • The design asset, implementation, documentation, accessibility contract, and regression coverage must ship in the same change.
Read the system construction standard

Visual specification

These measurements and semantic tokens define the supported visual contract. Local overrides should preserve the same hierarchy and interaction cues.

Label-to-trigger gap

8px

Trigger padding

16px left / 40px right / 12px vertical

Option padding

40px left / 16px right / 12px vertical

Radius

6px

Panel maximum height

240px

Panel offset

4px

Icons

16 × 16px

Rules

  • Keep option labels on one line when possible; rows truncate overflow.
  • The panel width follows the trigger.
  • Use the placeholder only before a meaningful value is selected.

Token dependencies

--color-surface2

Trigger and active option background.

--color-surface

Options panel.

--color-control-border / --color-control-border-strong

Trigger resting and hover boundaries.

--color-border

Options panel border.

--color-focus

Trigger focus outline.

--color-accent

Selected check marker.

--shadow-elevation-medium / --layer-dropdown

Options elevation and stacking.

States and behavior

A component is not complete until its passive, interactive, disabled, and exceptional states remain understandable in both themes.

closed

Trigger
Listbox is idle.
Visual response
Label and trigger show the current value or placeholder.
Behavior
Activation opens the options panel.

open

Trigger
Trigger is activated.
Visual response
Anchored options panel appears below the trigger.
Behavior
Focus and keyboard navigation move through options.
Accessibility
Headless UI exposes expanded and listbox relationships.

selected

Trigger
Option value matches value.
Visual response
Primary text, medium weight, and accent check.
Behavior
Choosing another option calls onChange and closes.

disabled

Trigger
Group or option is disabled.
Visual response
50% opacity and not-allowed cursor.
Behavior
Disabled trigger cannot open; disabled option cannot select.

Accessibility contract

Semantics, accessible naming, keyboard behavior, focus and announcements are implementation requirements, not optional documentation.

Semantics
Headless UI Listbox with labelled button, options, and managed focus.
Accessible name
Required visible label names the listbox.
  • Use stable unique option values.
  • Provide a selected value that exists in options or intentionally show the placeholder.
  • Disabled options must not be the only way to explain unavailable choices.
  • Do not replace the listbox with a native select when rich behavior is unnecessary without considering platform benefits.

Keyboard behavior

Enter / Space / Arrow Down
Opens the listbox and enters option navigation.
Arrow Up / Arrow Down
Moves the active option.
Enter / Space
Selects the active option.
Escape
Closes without changing selection.
Home / End
Moves to the first / last enabled option.
Typeahead
Moves to an option matching typed characters.

Implementation

Use the public package API and preserve the controlled-state, native-attribute, and ref contracts described below.

tsx
import { Dropdown, type DropdownOption } from '@ai-created/ui';

Client Component required

  • Generic string values preserve domain types.
  • The trigger button ref is forwarded.
  • Headless UI owns option roles, focus, and dismissal.
  • An Enter handler normalizes trigger opening behavior.
tsx
<Dropdown options={options} value={sort} onChange={setSort} label="Sort by" />

Public API

These props and helpers are compatibility contracts. Changes require migration guidance and release notes.

PropTypeDefaultContract
optionsDropdownOption<T>[]requiredOptions with value, label, and optional disabled.
valueTrequiredControlled selected value.
onChange(value: T) => voidrequiredCalled on selection.
labelstringrequiredListbox label.
placeholderstringSelect an optionFallback text.
disabledbooleanfalseDisables the listbox.

Usage guidance

These rules keep the component recognizable across products without preventing deliberate composition.

Do

  • Use for a moderate set of short, known options.
  • Sort or group options in a predictable domain order.

Do not

  • Do not use for two or three choices that should stay visible.
  • Do not use for large datasets that require search or virtualization.

Testing contract

The component should be verified as rendered UI, an interaction model, an accessibility surface, and a theme-aware visual artifact.

Unit

  • Resolves selected label and placeholder and forwards trigger ref.
  • Calls onChange with the selected enabled value.

Interaction

  • Open, arrow, select, escape, outside dismissal, typeahead, and disabled flows work.

Accessibility

  • Label, expanded state, active descendant/option semantics, and focus restoration are valid.

Visual

  • Capture closed/open, placeholder, selected, active, disabled option/trigger, overflow, themes, and top alignment beside a Field with an equal-height label.

Related specifications