call(back)

Typeahead with Keyboard Navigation

Build a typeahead: an input connected to a suggestions endpoint, with keyboard navigation. The endpoint is mocked in the starter (fetchSuggestions(query, signal) resolves after a jittered delay and honors an AbortSignal), so a slow old response really can arrive after a newer one. Available as a React template and an HTML/CSS/JS one.

Requirements

  • Debounce the query before fetching; ignore queries shorter than minChars.
  • A stale response must never overwrite a newer list — abort the in-flight request when the query changes.
  • Cache results by query so retyping a query doesn't refetch.
  • Arrow keys move the highlight and wrap around; Enter selects the highlighted item; Escape closes the list; clicking an item selects it.
  • Selecting an item fills the input and calls onSelect(item).
  • ARIA combobox wiring: role="combobox", aria-expanded, aria-activedescendant, and a role="listbox" of role="option"s.
  • Show loading, empty, and error states.

Hints

Hint 1

Debounce the value, not the handler: in React a useDebouncedValue(query, delay) hook whose effect sets the debounced value in a timeout and clears it in cleanup; in vanilla a debounce(fn, wait) around the search.

Hint 2

Fetch with an AbortController per request and abort the previous one when a new query arrives — in React the effect cleanup is that single line; in vanilla keep the controller in a closure variable.

Hint 3

Keep activeIndex and wrap with modulo in the keydown handler; mousedown + preventDefault on the list keeps the input focused so blur doesn't close it before the click lands.

Asked at