Build an accessible data table over 24 fixed { id, name, role, score } rows. Sorting, pagination, and selection must cooperate without turning the visible eight rows into a second source of truth.
The polished starter renders the complete resting view, but its controls are intentionally inert. Add React state, derivations, event handlers, and the live accessibility state.
Name, Role, or Score sorts ascending; clicking the same header again toggles descending. A ▲/▼ arrow marks the active column. Sorting jumps back to page 1.Prev / page numbers / Next and a Page X of 3 readout. Prev is disabled on page 1, Next on the last page.Set. The header checkbox selects or deselects every row on the current page. It is checked when all eight are selected and indeterminate when only some are selected. A N selected readout shows selected.size, and selected ids persist as you page.<th> cells, expose aria-sort on each sortable header, label every checkbox, mark the current page with aria-current="page", and announce the selection and page readouts with aria-live="polite".aria-sort, checked/indeterminate header checkbox, selected-row treatment, live readouts, disabled boundaries, and aria-current must always match state.Score once: rows reorder low-to-high with a ▲ on Score. Click Score again: high-to-low with a ▼. Click Name: back to ▲, now on Name, and you snap to page 1.8 selected shows. Go to page 2 — its rows are unticked, but page 1's selection is remembered when you return.sort(ROWS) → slice(page) computed during render, not a second piece of state you keep in sync.Set<number> of ids so it survives sorting and paging; don't tie it to row positions.Set rather than mutating it, and synchronize the checkbox's DOM-only indeterminate property with a ref and effect.styles.css and remains in place when the solution replaces App.tsx.The full solution is part of Premium
Walkthrough, edge cases, complexity notes, and the runnable editor unlock with a Premium subscription.
Submissions are part of Premium
Unlock community code, comments, reactions, and framework-specific approaches.
Build an accessible data table over 24 fixed { id, name, role, score } rows. Sorting, pagination, and selection must cooperate without turning the visible eight rows into a second source of truth.
The polished starter renders the complete resting view, but its controls are intentionally inert. Add React state, derivations, event handlers, and the live accessibility state.
Name, Role, or Score sorts ascending; clicking the same header again toggles descending. A ▲/▼ arrow marks the active column. Sorting jumps back to page 1.Prev / page numbers / Next and a Page X of 3 readout. Prev is disabled on page 1, Next on the last page.Set. The header checkbox selects or deselects every row on the current page. It is checked when all eight are selected and indeterminate when only some are selected. A N selected readout shows selected.size, and selected ids persist as you page.<th> cells, expose aria-sort on each sortable header, label every checkbox, mark the current page with aria-current="page", and announce the selection and page readouts with aria-live="polite".aria-sort, checked/indeterminate header checkbox, selected-row treatment, live readouts, disabled boundaries, and aria-current must always match state.Score once: rows reorder low-to-high with a ▲ on Score. Click Score again: high-to-low with a ▼. Click Name: back to ▲, now on Name, and you snap to page 1.8 selected shows. Go to page 2 — its rows are unticked, but page 1's selection is remembered when you return.sort(ROWS) → slice(page) computed during render, not a second piece of state you keep in sync.Set<number> of ids so it survives sorting and paging; don't tie it to row positions.Set rather than mutating it, and synchronize the checkbox's DOM-only indeterminate property with a ref and effect.styles.css and remains in place when the solution replaces App.tsx.The full solution is part of Premium
Walkthrough, edge cases, complexity notes, and the runnable editor unlock with a Premium subscription.
Submissions are part of Premium
Unlock community code, comments, reactions, and framework-specific approaches.
Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.