Skip to content

feat: Tanstack Table + virtual scroll with column picker and URL state#1016

Open
gianpaj wants to merge 9 commits intoanomalyco:devfrom
gianpaj:feat/tanstack-table
Open

feat: Tanstack Table + virtual scroll with column picker and URL state#1016
gianpaj wants to merge 9 commits intoanomalyco:devfrom
gianpaj:feat/tanstack-table

Conversation

@gianpaj
Copy link

@gianpaj gianpaj commented Feb 24, 2026

Closes: #977

It's so much fast now!

modes.dev-fast-tabele.mp4

Summary

  • Replaces static server-rendered table rows with client-side Tanstack Table (vanilla JS) + virtual row scrolling via @tanstack/virtual-core
  • Adds a column picker dropdown (grouped checkboxes, Show All button) so users can show/hide any of the 24 columns
  • Syncs table state (search, sort, visible columns) to URL query params for shareable links and browser history

What changed

  • packages/web/src/data.ts — new Row type and flattenProviders() to convert api.json → flat row array
  • packages/web/src/url-state.tsparseUrlState / serializeUrlState for ?search=&sort=&order=&cols=
  • packages/web/src/columns.ts — 24 ColumnDef<Row> definitions with safe DOM cell renderers (no innerHTML)
  • packages/web/src/index.ts — full rewrite using createTable + new Virtualizer(); only ~35 DOM rows rendered at a time regardless of dataset size
  • packages/web/src/render.tsx — stripped to HTML shell (empty <thead>/<tbody>); no more server-baked rows
  • packages/web/src/index.css — virtual scroll container, sticky thead, column picker styles, data-column-id based column styling (replaces fragile nth-child selectors)

Test Plan

  • All 12 unit tests pass (bun test)
  • bun run build produces clean dist with no baked-in <tr> rows in HTML
  • Table loads and renders rows from /api.json in browser
  • Sorting by any column works; sort order persists in URL
  • Search filters rows; Cmd+K focuses search input
  • Column picker shows/hides columns; URL cols= param updates
  • Browser back/forward restores table state
  • Provider logos load from /logos/{id}.svg

🤖 Generated with Claude Code

gianpaj and others added 7 commits February 24, 2026 07:05
Replaces imperative sort/filter/render with declarative Tanstack Table
(createTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel)
and virtual row rendering via Virtualizer class. Adds column picker
dropdown, URL state sync (search/sort/order/cols), and keyboard
shortcut Cmd+K to focus search.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n-id to tds

- Add #table-scroll-container with full-viewport scroll height
- Make thead th sticky at top:0 within scroll container
- Replace nth-child column selectors with data-column-id attribute selectors
- Add column picker dropdown styles (.picker-group, .picker-item, etc.)
- Add .provider-logo img style; remove stale .provider-cell svg rule
- Add #table-loading style
- Add data-column-id to each td in renderRows()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gianpaj gianpaj marked this pull request as draft February 24, 2026 06:38
In vanilla JS, Virtualizer._willUpdate() must be called manually to
initialize scroll element observation (frameworks call it automatically
via lifecycle hooks like useLayoutEffect). Without it, scrollElement
stays null, observers are never set up, and getVirtualItems() always
returns an empty array.

Also added /api.json route to the dev server so the client-side fetch
succeeds in development mode.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gianpaj gianpaj marked this pull request as ready for review February 24, 2026 07:13
@kylhuk
Copy link

kylhuk commented Feb 28, 2026

Adding virtual scroll eliminates the possibility to use the search of a browser, without showing this the user. From a usability point of perspective, this is not recommended. If the number of rows is an issue, paging would be a viable solution to this problem, with the possibility to override the number of rows shown.

@gianpaj
Copy link
Author

gianpaj commented Mar 3, 2026

@kylhuk that's not true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web: Select columns to display and improve web performance

2 participants