Question presented to candidate: "Build the left navigation for our dashboard. It has top-level pages and a couple of groups with sub-pages. Users can collapse it to a narrow icons-only rail to get more room, and it should remember that choice next time they visit. The current page must be clearly highlighted."
Requirements:
- Render nested navigation data: top-level links and groups with child links.
- Each group expands and collapses independently; the group holding the active page starts expanded.
- A toggle collapses the sidebar to an icons-only rail and expands it again; the collapsed state survives a reload (localStorage, with failures handled).
- Clicking a link makes it the active page, highlighted and marked
aria-current="page"; the main area shows the current page. - In the rail, labels are visually hidden but still the accessible names, icons show a native tooltip, the group holding the active page is marked, and clicking a group expands the sidebar and opens that group.
What a strong answer should cover:
- A data-driven render from a nested array, with a small state model:
collapsed, a set of open group ids, and the active id owned by the parent (or the router). - Derived values: a group is shown expanded only when it is open and the sidebar is not collapsed.
- Disclosure ARIA (
aria-expanded,aria-controls,hidden) inside anavlandmark, notrole="menu". - Visually hidden labels instead of
display: none, so the rail keeps accessible names. - Safe persistence: read once on start, write on change, wrapped in try/catch.
Clarifying questions expected:
- "Does the active page come from the router (URL), or is it local state?"
- "Should open groups be remembered too, or only the collapsed state?"
- "On mobile, should it become an overlay drawer instead?"
Code / implementation expected: Yes. A sidebar component, the nav data and a page that shows the current item; CSS width transition.