Question presented to candidate:
"Our editor has a file sidebar next to the main area. Build a draggable divider so users can resize the sidebar, and package the logic as a reusable hook, something like const { size, handleProps } = useResizable({ initial: 280, min: 180, max: 480 }). It should work with a mouse, touch and the keyboard, and remember the width."
Requirements:
- A sidebar and a main area with an 8 px divider between them; dragging the divider changes the sidebar width.
- Width clamped between
minandmaxno matter where the pointer goes, including far outside the window. - Pointer events (mouse, touch, pen), only for the primary button, with no text selection while dragging.
- Keyboard: the divider is focusable; Left and Right change the width by a step, Shift for a bigger step, Home and End jump to min and max; double-click resets.
- Proper separator semantics:
role="separator",aria-valuenow,aria-valuemin,aria-valuemax,aria-controls. - The width persists in localStorage, written when a drag ends rather than on every move, and storage failures do not break the widget.
- The logic lives in a reusable hook (or composable or directive) with a small API.
What a strong answer should cover:
- Computing the size from the drag's start position (
startSize + clientX - startX) rather than accumulating deltas, so it cannot drift. - Listening for
pointermoveandpointeruponwindow(or usingsetPointerCapture) so a fast drag that leaves the handle keeps working, and removing those listeners onpointerup,pointercanceland unmount. touch-action: noneon the handle so touch drags do not scroll the page.- Clamping, and what to do when
maxis larger than the space available. - Hook API design: returning prop getters versus spreading an object, and keeping persistence optional.
- Accessibility of the window splitter pattern.
Clarifying questions expected:
- "Horizontal only, or should the hook support vertical resizing too?"
- "Should the width persist per user, per page or not at all?"
- "Are there several panels, or exactly one handle?"
Code / implementation expected: Yes. The hook and a two-panel layout using it.