Build: Autocomplete
Introduction
Autocomplete looks like a simple filtered list, but a complete machine-coding answer must handle input delay, ranking, keyboard navigation, selection, empty state, accessibility attributes, and cleanup.
The best interview solutions separate the suggestion source from the widget. That lets you use a local list, a trie, or a remote API without rewriting the keyboard and rendering logic.
Why This Matters
Autocomplete appears in search bars, command palettes, address forms, IDEs, and admin dashboards. Interviewers expect you to discuss both algorithmic lookup and product-quality behavior: arrow keys, Enter, Escape, active option highlighting, and avoiding stale async results.
Theory
Data structure choice
For small local lists, filtering with startsWith and includes is simpler and often fast enough. For large static dictionaries, a trie gives efficient prefix lookup. For remote suggestions, debounce the query and use the same stale-response guard as debounced search.
Widget state
The widget needs four pieces of state: current query, current suggestions, active index, and open/closed status. Keyboard events mutate active index without changing the query. Selecting an item writes the label to the input, closes the panel, and calls onSelect.
Accessibility
Use role="combobox" on the input, role="listbox" on the panel, and role="option" on each item. Keep aria-expanded and aria-activedescendant in sync with the open state and highlighted option. These details are often not required to pass a basic round, but they turn a good solution into a production one.
Visual Diagrams
input change | v debounce query | v get suggestions | v render listbox | +--> Arrow keys change active index +--> Enter or click selects option +--> Escape closes list
Typing and navigation are separate flows that share one rendered list.
Code Examples
Complete autocomplete widget
This implementation uses an injected getSuggestions function, so the same component can work with a local array, trie, or remote service.
Playground
Press Run to execute the code and see output here.
Output Prediction
Predict the output #1
1function rankSuggestions(items, query, limit) {2 var normalizedQuery = query.toLowerCase();3 var prefix = [];4 var contains = [];5 6 items.forEach(function (item) {7 var label = item.toLowerCase();8 9 if (label.indexOf(normalizedQuery) === 0) {10 prefix.push(item);11 } else if (label.indexOf(normalizedQuery) !== -1) {12 contains.push(item);13 }14 });15 16 return prefix.concat(contains).slice(0, limit);17}18 19console.log(rankSuggestions(['React', 'Redux', 'Preact', 'Reason', 'Vue'], 'rea', 3).join(','));Coding Exercises
Implement accessible autocomplete
HardBuild createAutocomplete(options).
Requirements:
- Accept
{ input, panel, getSuggestions, onSelect, delay, limit }. - Debounce suggestion loading.
- Ignore stale suggestion responses.
- Render a selectable list with mouse support.
- Support ArrowDown, ArrowUp, Enter, and Escape.
- Maintain basic ARIA combobox/listbox/option attributes.
- Return
destroy().
Constraints:
- Do not use a framework.
- Keep lookup pluggable; do not bake fetch or a hard-coded array into the widget.
Interview Questions
1When would you choose a trie for autocomplete?
Use a trie when the data set is large, mostly static, and prefix lookup is the dominant operation. A trie can find a prefix node in O(m), where m is the query length, then collect results below it. For small lists or remote APIs, simple filtering or server-side search is usually better.
Follow-ups
- How would you cap memory usage in a trie?
- How would you rank by popularity and recency?
2Why use `mousedown` for selecting an option?
Click fires after the input can lose focus. If blur closes the panel first, the clicked option may disappear before selection. Handling mousedown and calling preventDefault lets selection happen before the blur behavior.
Quiz
1. Which state is required for keyboard navigation?
Summary
- Keep lookup pluggable so the UI works with local lists, tries, or remote APIs.
- Autocomplete state includes query, suggestions, active index, and open/closed status.
- Keyboard and mouse selection must be handled separately from input changes.
- ARIA roles and active-descendant attributes make the widget closer to production-ready.
Cheat Sheet
Autocomplete checklist
- Debounce suggestion loading.
- Ignore stale async responses.
- State: suggestions, activeIndex, open.
- Keys: ArrowDown, ArrowUp, Enter, Escape.
- Mouse: prefer
mousedownfor option selection. - ARIA: combobox, listbox, option, expanded, active descendant.
- Data: filter for small lists, trie for large static prefixes, server for global search.