Question presented to candidate: "Let's start simple. Build me a todo list in the browser: I type a task and press Enter or click Add, it appears in the list, I can tick it off, rename it in place and delete it. Show how many are left, and let me filter between all, active and completed. No libraries, just the framework."
Requirements:
- Add a task with a text field plus Enter or an Add button; trim whitespace and reject blank or duplicate (case-insensitive) text with a visible message.
- Each row: a checkbox to mark it complete, an Edit control that swaps the text for an input (Enter or Save commits, Escape or Cancel throws the edit away), and a Delete button.
- A live "N items left" count with correct singular and plural.
- Filters: All / Active / Completed, with the active filter visibly selected and an empty-state message when nothing matches.
- Works with the keyboard and announces errors to screen readers.
What a strong answer should cover:
- One array of
{ id, text, done }objects as the single source of truth; the visible list and the remaining count are derived from it during render, not stored separately. - Controlled inputs: the text field's value comes from state and every keystroke goes through a change handler.
- Immutable updates (
map,filter, spread) so the framework sees a new array, plus stable unique keys (an id, never the array index) for list rows. - A real
<form>with a submit handler so Enter works for free, andpreventDefaultto stop the page reload. - Edit mode as a small piece of per-row or lifted state, with focus moved into the edit box and Escape to cancel.
- Accessible names on icon buttons,
aria-pressedon filter toggles, and anaria-liveregion for validation errors.
Clarifying questions expected:
- "Should tasks survive a page reload, or is in-memory state fine?"
- "Are duplicate task names allowed, and what should happen when I save an edit as blank?"
- "Is the order fixed (newest last), or do you want sorting or drag to reorder?"
Code / implementation expected: Yes. A working component in the chosen framework (React, Vue or Angular), about 100-150 lines, with add, toggle, inline edit, delete, filters and the remaining count.