Question presented to candidate: "Our help page has a long FAQ. Build an accordion component: a list of questions where clicking a question shows or hides its answer. By default only one answer should be open at a time, but the same component should also support letting several stay open. Make it usable with a keyboard and a screen reader."
Requirements:
- Data-driven: the component takes an array of items (
id,title,content) and renders one header and one panel per item. - Clicking a header toggles its panel. A prop switches between single-open (opening one closes the others) and multi-open mode; a
defaultOpenlist sets the initial state. - Each header is a real
<button>inside a heading, witharia-expandedandaria-controls; each panel is aregionlabelled by its header. Closed panels must not be reachable with Tab. - Keyboard: Enter and Space toggle (native button behaviour); Arrow Down / Arrow Up move between headers and wrap; Home and End jump to the first and last header.
- Opening and closing animates the height smoothly, and the animation is turned off for users who ask for reduced motion.
What a strong answer should cover:
- A single source of truth for which panels are open (a list of ids), with the single-open view derived from it rather than kept in a second piece of state.
- Correct WAI-ARIA accordion wiring: heading plus button,
aria-expanded,aria-controls,role="region"witharia-labelledby, and unique ids per instance. - Why closed content must be removed from the tab order and the accessibility tree (
hiddenorinert), not just squashed to zero height. - Animating height without measuring it (the
grid-template-rows: 0frto1frtechnique) and respectingprefers-reduced-motion. - Roving focus between headers with arrow keys, and leaving Enter and Space to the native button.
Clarifying questions expected:
- "Should one panel always stay open, or may every panel be closed?"
- "Do panels hold heavy content that should only render when first opened, or is it fine to render everything up front?"
- "Does the open state need to survive a reload or be shareable in the URL?"
Code / implementation expected: Yes. A working component in the chosen framework, with a small demo that toggles between single and multi mode.