Skip to the solution
HardMachine Coding10 min read

Build a Combobox (search + select)

92 views

The problem

Question presented to candidate: "Build a reusable combobox for a 'Favourite language' field: the user can type to filter the options or open the full list, move with the keyboard, and select one value. It must follow the WAI-ARIA combobox pattern closely enough that a screen-reader user can use it, and the parent form must be able to read and set the value."

Requirements:

  • Controlled component: the parent owns value (an option id or null) and receives changes; the input shows the selected option's label, and a value set from outside updates the label.
  • Typing filters options (case-insensitive substring) and highlights the first enabled match automatically; Enter commits it; leaving the field (Tab, click elsewhere) also commits the highlighted match, and with no match the previous label is restored.
  • Down / Up open the list (on the selected option, or the first / last) and move with wrap-around, skipping disabled options; Alt+Down opens without highlighting; Escape closes and restores the label, and a second Escape clears the value.
  • A toggle button (โ–พ) and a clear button (ร—) that never take focus away from the input; mouse hover highlights, click commits, disabled options cannot be chosen.
  • DOM focus always stays in the input; the highlighted option is exposed with aria-activedescendant; a polite live region announces the number of options.

What a strong answer should cover:

  • The difference between the text in the input, the filter, the highlighted (active) option and the committed value, and why they are separate pieces of state.
  • The ARIA wiring: role="combobox", aria-autocomplete="list", aria-expanded, aria-controls, aria-activedescendant, role="listbox" / role="option", aria-selected, aria-disabled, unique stable ids.
  • A keyboard map for the closed and open states, and the blur rule for "list autocomplete with automatic selection".
  • mousedown preventDefault on options and buttons so focus never leaves the input.
  • Scrolling the active option into view, and how the component exposes its value (props + callback, v-model, [(value)] / ControlValueAccessor).

Clarifying questions expected:

  • "Must the value be one of the options, or is free text allowed?"
  • "Should the first match be highlighted automatically, and should leaving the field commit it?"
  • "Are options local or loaded from a server? How many?"

Code / implementation expected: Yes. A reusable, controlled combobox component with full keyboard support and correct ARIA attributes.

  • React
  • Combobox
  • Async

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

10 min read ยท 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { useState } from "react";
import Combobox from "./src/components/Combobox";
import { LANGUAGES } from "./src/utils/options";

export default function App() {
  const [lang, setLang] = useState("rs");
  return (
    <main className="page">
      <h1>Profile</h1>
      <Combobox
        label="Favourite language"
        options={LANGUAGES}
        value={lang}
        onChange={setLang}
      />
      <p className="value" data-testid="value">
        Form value: {lang === null ? "null" : JSON.stringify(lang)}
      </p>
      <button
        type="button"
        className="secondary"
        data-testid="reset"
        onClick={() => setLang("ts")}
      >
        Set to TypeScript from outside
      </button>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 107 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

End of the topic

That was the last Machine coding question.

Pick another topic