30% offEnding soon
FSD-002Frontend system design Premium

Design a Production Dropdown and Select Primitive

Design an accessible dropdown and select primitive with sound semantics, focus, positioning, state APIs, performance, and testing.

Intermediate 34 min read

A production dropdown starts with semantics, not coordinates. Decide whether the control selects a value, runs an action, accepts typed text, or only reveals content. Then design one explicit state machine for opening, navigation, commitment, dismissal, focus, and positioning. Use the native <select> whenever it meets the product requirements.

“Dropdown” is how a popup looks. It does not tell an engineer what the popup means. A country field, an account-actions menu, an autocomplete, and a help disclosure can all open beneath a button. They need different roles, keyboard behavior, state, and form contracts.

This interview question asks you to design a reusable single-select primitive for a component library. The basic product has a labelled trigger, a popup list of options, keyboard and pointer input, disabled options, option groups, typeahead, form participation, and enough positioning logic to work inside real application layouts.

Start by choosing the right semantic family

The first design decision is whether to build anything custom.

Use a native <select> when the options are plain, the browser's mobile picker is welcome, and exact popup styling is not a requirement. Native form submission, constraint validation, keyboard behavior, and platform accessibility come with it.

If users choose one value from a fixed list and the closed control must expose that value, the custom version is usually a select-only combobox with a listbox popup. The W3C combobox pattern distinguishes this from an editable combobox. If the popup contains actions such as Rename or Delete, it is a menu button instead. If it contains links, buttons, and general content, neither listbox nor menu may be the right abstraction.

The public interview prompt

Design a dropdown and single-select primitive for a frontend design system. Explain:

  • when the library should render a native select and when it should use a custom popup;
  • the controlled and uncontrolled API;
  • selected, active, open, disabled, and pending state;
  • keyboard, pointer, touch, screen-reader, zoom, and right-to-left behavior;
  • popup positioning, clipping, portals, stacking, and outside interaction;
  • large option sets, typeahead, virtualization, and asynchronous options;
  • form submission, validation, server rendering, and hydration;
  • testing, observability, rollout, and failure containment.

Assume a single-select field with up to 200 local options in the normal case. Searching a remote catalog and multi-select behavior are separate primitives that may reuse lower-level pieces. The trigger must work in forms, dialogs, scroll containers, mobile layouts, and pages rendered on the server.

What the premium solution covers

The full solution works from the semantic decision through the production architecture. It includes original mobile-friendly diagrams, a state and event model, typed API contracts, positioning middleware, portal ownership, focus strategies, typeahead, form integration, performance budgets, degraded behavior, security boundaries, a test matrix, rollout metrics, an interview walkthrough, and a level-by-level scoring rubric.

The core invariant is small enough to remember: the closed trigger shows the committed value; opening creates a temporary active candidate; only an explicit commit changes the value. Escape, blur, scrolling, disabled options, controlled updates, and portal events all have to preserve that rule.

Premium solution

Continue with the complete system design

Unlock the architecture, state machine, API contracts, original diagrams, positioning model, accessibility decisions, performance budgets, testing plan, rollout strategy, scoring rubric, and interview walkthrough.

  • Detailed, beginner-friendly explanation
  • Production failure modes and trade-offs
  • Mobile-friendly architecture diagrams
  • Senior and staff-level interview signals
Unlock Premium

Frequently asked questions

What is a dropdown in frontend system design?
Dropdown is a visual description, not one accessibility role. The design must first decide whether the popup chooses a value, runs an action, filters options, or reveals ordinary content. That decision leads to a select, listbox, combobox, menu button, or disclosure pattern.
When should a design system use the native select element?
Use the native select when its form behavior, mobile picker, keyboard support, and accessibility are more important than custom option layout or exact popup styling. A custom primitive is justified only when product requirements cannot be met reliably with the native control.
Should a custom select use menu roles?
Usually no. A select chooses and exposes a value, while a menu offers actions or commands. A custom single-select normally follows the select-only combobox pattern with a listbox popup, or uses a standalone listbox when the list remains visible.
Where should focus go when a custom select opens?
Pick one documented focus model. A select-only combobox can retain DOM focus on the trigger and identify the active option with aria-activedescendant. A roving-tabindex listbox can move DOM focus between options. Do not mix both models.
How should a dropdown avoid clipping near the viewport edge?
Measure the trigger and popup after both exist, prefer a logical placement such as block-end start, then flip, shift, or constrain the popup when space is limited. Recompute while open when scrolling, resizing, zooming, or layout changes move either element.
Should the popup always render in a portal?
No. Keeping it beside the trigger preserves DOM order and inherited context. Use a portal when clipping, stacking, or overlay ownership requires it, then preserve accessible relationships, outside-press boundaries, event behavior, and cleanup across both DOM branches.
What is the difference between active and selected options?
The selected option is the committed value. The active option is the temporary keyboard or pointer target while the popup is open. Escape should usually discard the active candidate and keep the selected value.