Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Combobox Suggestions and Active Option

Last updated: 5 Oct 20266 min read
tutorial
IntermediateBy AITrove Editorial

An editable combobox pairs a text input with a suggestion popup. It is more than a filtered list: the input needs a label, an expanded state, a relationship to the popup, a stable active option, and keyboard behavior for opening, moving, accepting, and dismissing suggestions. In a common pattern, DOM focus stays on the input while aria-activedescendant points to the active option. The referenced option must exist in the mounted popup and its ID must remain stable for the duration of that state. Down Arrow moves through available suggestions; Escape closes the popup; Enter accepts the active choice. Ordinary text-editing keys must keep their platform behavior.

Working case

A reviewer assigns case 47 to a colleague by typing a name. Suggestions arrive asynchronously, and the highlighted person changes after a newer query. The input currently says 'Ari', but an older 'Ar' request returns and replaces the popup. The active option ID now points to an unmounted row; a screen reader receives no useful suggestion. Tie results to the current query generation, keep the active index within bounds, and clear the active descendant when the list closes. A pointer click and keyboard Enter must commit the same person ID, not just the visible label.

Implementation boundary

javascript
function nextOptionIndex(current, direction, count) {
  if (count === 0) return -1;
  return Math.min(count - 1, Math.max(0, current + direction));
}
console.log(nextOptionIndex(1, 1, 3));
// Output: 2

The index helper handles bounds; the component still needs a real label, input semantics, popup ownership, and a stable option-ID scheme. On query change, invalidate old results and decide whether to reset selection or preserve it only when the same option remains. Keep DOM focus on the input in the active-descendant model, and do not prevent default for printable keys or caret movement. Set expanded state only while the popup is actually visible. Announce result count sparingly; updating a live region on every keystroke can drown out the typed text. Provide a simple native selection alternative if the data set is small enough.

Cost and boundaries

Filtering n local options is O(n) per query; server search trades that work for network requests and ordering races. Rendering all n options can become expensive, but virtualizing the active option out of the DOM breaks the active-descendant reference. Keep a bounded result count or ensure the active item stays mounted. A debounce reduces requests but increases feedback delay. Accessibility work adds state transitions and testing time, which is why a native select or datalist may be preferable when its behavior meets the product need.

Failure trace

The popup is hidden visually, but aria-expanded remains true and aria-activedescendant points to an option that was removed. Keyboard focus remains in the input while assistive technology expects a suggestion that no longer exists. Clear both states together on Escape or result replacement. Another implementation steals DOM focus into the list and breaks text editing; choose one focus model and test it. A delayed old response must not replace the latest query's suggestions or the selected person ID.

Verification

  • The active-descendant target exists whenever it is referenced.
  • Escape closes suggestions without losing the input's text-editing path.
  • Old search results cannot replace a newer active list.

Practice drill

Type 'Ar', then 'Ari', and return the first request last. Confirm the popup still represents 'Ari'. Use Down Arrow, Up Arrow, Enter, Escape, Tab, Home, and End while checking that text editing remains possible. Delete all text and verify the active descendant is cleared when no options remain. Select by pointer and keyboard and compare submitted person IDs. Shrink results while the final option is active; focus should move to a valid mounted option or return to the input clearly.

Decision note

Implement one focus model completely and keep active option, popup visibility, and current query in agreement.

Common Mistakes

  • Using a listbox role without maintaining input and popup state.
  • Referencing an unmounted active option after filtering.
  • Stealing focus from an editable input on every arrow key.

Connected lessons

Complex Accessible Interactions; Data Table Versus Interactive Grid; Reorder Controls Without Dragging; Async Status Announcements and Focus; Asynchronous Field Validation Races; Search Query Normalization and Ranking; Accessible forms: connect labels, errors, and focus.

Apply and check

Build Project: accessible operations workspace and review Web Development: streams and interaction decisions quiz.

web-tech
web-development
Storage details