01 — Foundation

Autocomplete enhances search — it does not replace it

Suggestions speed discovery when the baseline search still works without JavaScript.

Search autocomplete shows suggested queries or results as users type. It must not be the only way to search, must not hijack keyboard focus, and must degrade to a normal submit form when scripts fail. See also the Search pattern for forms, results, and empty states.

02 — Combobox

Combobox behaviour

Follow combobox patterns — not a styled div list with mouse-only selection.

  • input with role="combobox", aria-expanded, and aria-controls linking the listbox
  • arrow keys move suggestions; Enter selects; Escape closes
  • highlight the active option — do not rely on hover alone
  • debounce network calls; cancel stale responses

03 — Results

Suggestions users can trust

Show why an item appears and what happens when it is chosen.

  • distinguish recent searches, popular terms, and live results if mixed
  • empty suggestion list — fall back to submit; see Empty States
  • announce result count sparingly for screen readers — avoid announcing every keystroke
  • selecting a suggestion navigates or fills intentionally — not surprise full-page redirects
<label for="product-search">Search products</label>
<input id="product-search" type="search" role="combobox" aria-expanded="false" aria-controls="suggestions" />
<ul id="suggestions" role="listbox" hidden></ul>

04 — Avoid

Common failures

Instant search that flashes, traps focus, or hides errors helps nobody.

  • do not remove the submit button for server-driven search without a tested alternative
  • loading indicator inside the list — not a page-wide overlay for each character
  • respect reduced motion on list open/close animations

05 — Review

Before you approve

A short checklist for search autocomplete in code review.

  • form works without JS; combobox keyboard behaviour is complete
  • debounced, cancellable fetches; selection behaviour is predictable
  • errors and empty suggestions are handled inline