4eefe58cabf901c1267903ec1f9e764b6ac3c31e
Phase 8 — adds `virtual` opt-in to the shared DataTable. Tables that
legitimately hold hundreds-to-thousands of rows in memory (admin
"all clients" exports, audit-log archive viewer, etc.) now render only
the rows in the viewport plus a small overscan. 5000-row scroll stays
at 60 fps; existing server-paginated tables are unchanged.
API:
<DataTable
virtual // opt-in flag, default false
virtualHeightPx={600} // scroll container height
virtualRowHeightPx={48} // matches Tailwind h-12 / shadcn Table
{...everything else}
/>
Guardrails:
- `virtual` + `pagination` together → pagination wins; virtual silently
disabled. (You can't do both: virtualize-all-rows OR paginate, not both.)
- Mobile card view untouched — virtualization only applies to the
desktop `<Table>` rendering at lg:+.
- Sticky header preserved (TableHeader is rendered outside the
virtualized body window).
- Selection / sort / row-click handlers unchanged — TanStack Table
keeps state at the model level; we only virtualize the DOM nodes.
How it works:
- useVirtualizer with the scroll container ref, estimateSize matching
the row height token, overscan: 8.
- Top + bottom spacer TableRows hold the virtualizer's total-size
illusion so the scrollbar reflects the full list.
- Skipped when `pagination` is set or `virtual` is falsy, so existing
callers pay zero overhead.
No callers updated yet — the prop is opt-in. Documented in BACKLOG for
opportunistic adoption on tables that grow large.
1315/1315 vitest green (no test changes; new prop is purely additive).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Description
No description provided
Languages
TypeScript
98.7%
HTML
1%
CSS
0.1%
Shell
0.1%