Skip to content

docs(examples): use spacer rows instead of translateY in the table examples - #1338

Open
dgesteves wants to merge 1 commit into
TanStack:mainfrom
dgesteves:docs/table-examples-spacer-rows
Open

dgesteves wants to merge 1 commit into
TanStack:mainfrom
dgesteves:docs/table-examples-spacer-rows

Conversation

@dgesteves

@dgesteves dgesteves commented Oct 24, 2026 •

Copy link
Copy Markdown

🎯 Changes

Fixes #585.

The React, Vue, Svelte and Angular table examples moved each row with translateY(start - index * size) inside a div sized to getTotalSize(). The <table> was only as tall as the rendered rows (roughly 560 to 2,200px, against 1,700,000px of rows), so most rows were drawn outside it. That's why a sticky header scrolls away and row borders disappear, as described in the issue.

Following the approach suggested in the issue thread and in #476, the examples now render a spacer row above and below the visible rows:

  • Top spacer: virtualRows[0].start. Bottom spacer: getTotalSize() - lastRow.end. Each spacer is a single <td colSpan>.
  • The wrapper div and the transforms are removed, so the table is exactly as tall as all of its rows.
  • thead is position: sticky; top: 0 with a background.
  • border-collapse: collapse on the table. With the default 2px border spacing each row took 36px while the virtualizer assumed 34px.
  • overflow-anchor: none on the scroll container, so scroll anchoring doesn't adjust scrollTop when the spacer heights change.
  • Vue: rows now get height: virtualRow.size like the other examples. Before, they rendered at their natural height (around 20px), which left blank space at the bottom of the viewport.
  • Svelte: this example has no global box-sizing: border-box, so the spacer cells set padding: 0 to keep their height exact.
  • The intro paragraph in each example described the old translateY trick, so I rewrote it.

The Marko table example already sizes its table to the total size, so I didn't change it. There are no Solid or Lit table examples. Most of the diff is re-indentation from removing the wrapper div (git diff -w is 169+/56-).

Testing: I ran each example in both the dev server and the production build. I checked each one with a headless Playwright script in Chromium, Firefox and WebKit at scroll offsets 0, 3,400, 100,017, 850,000, 1,234,567 and the max. At each offset the script checked that:

  • the table height equals the header plus 50,000 x 34px
  • the header is pinned to the top of the scroll container
  • the row under the header matches the offset
  • every rendered row is at (id - 1) * 34px from the top of the tbody
  • row 50,000 is the last visible row at the max offset

It also wheel-scrolled (scrollTop only increased and the header stayed pinned), sorted by ID, and jumped to the end. All four examples passed in all three browsers. On main the same script fails on table height and the sticky header.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr. (test:sherif, test:docs and the build targets for the four examples pass. test:knip fails for me on an unmodified main checkout too, flagging scripts/verify-*.ts and markdown-link-extractor, so it's unrelated to this change.)

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Happy to take suggested changes, for example putting the sticky styles on th instead of thead, or splitting the non-React examples into a separate PR.

Summary by CodeRabbit

  • Examples
    • Updated the Angular, React, Svelte, and Vue table examples to render virtualized rows with spacer rows above and below the visible content.
    • Kept table headers visible while scrolling in the React, Svelte, and Vue examples.
    • Updated the instructional text to explain the spacer-row approach.

…amples

The React, Vue, Svelte and Angular table examples moved each row with
translateY inside a div sized to getTotalSize(). The <table> itself only
grew to the height of the rendered rows, so a sticky header scrolled
away once the rows were translated past the end of the table.

Render a spacer row above and below the visible rows instead, so the
table is as tall as all of its rows, and make the header sticky. Also
collapse the default border spacing so rows are exactly the estimated
34px, set explicit row heights in the Vue example, and turn off
overflow-anchor on the scroll container.

Fixes TanStack#585
@changeset-bot

changeset-bot Bot commented Oct 24, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 990cd38

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: aa36763e-94c9-4100-913d-25dbdc7b53fb
Commits

Reviewing files that changed from the base of the PR and between c462c61 and 990cd38.

Files selected for processing: 6
  • examples/angular/table/src/app/app.component.ts
  • examples/react/table/src/index.css
  • examples/react/table/src/main.tsx
  • examples/svelte/table/src/App.svelte
  • examples/vue/table/src/App.vue
  • examples/vue/table/src/style.css

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

The Angular, React, Svelte, and Vue table examples now render visible virtual rows between top and bottom spacer rows. The examples remove translated row positioning and add styles for sticky headers, collapsed borders, and disabled scroll anchoring.

Changes: Virtual table examples

Layer / File(s) Summary
Spacer-row rendering
examples/angular/table/src/app/app.component.ts, examples/react/table/src/main.tsx, examples/react/table/src/index.css, examples/svelte/table/src/App.svelte, examples/vue/table/src/App.vue, examples/vue/table/src/style.css
The examples calculate spacer heights from virtual row positions and render the visible rows between spacer rows. They remove the fixed-height wrapper and translated row positioning. Table styles add sticky headers, collapsed borders, and disabled scroll anchoring. Explanatory text describes the spacer-row approach.

Priority: Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: kouts, garrettld, marcusvirg

Merge Risk: Minimal · up to 990cd

No concrete merge-blocking issue remains in the updated table examples.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (4 skipped: 4 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the main change: replacing translateY positioning with spacer rows in the table examples.
Description check Passed The description includes the required Changes, Checklist, and Release Impact sections. It explains the motivation, implementation details, testing results, and why pnpm run test:pr was not run. The un…
Linked Issues check Passed The active directly linked issue is #585. The React example now renders top and bottom spacer rows from the virtual range, removes translated rows and the fixed-height wrapper, and keeps the table siz…
Out of Scope Changes check Passed The changes to Vue, Svelte, and Angular apply the same table-sizing fix to equivalent virtual table examples. Their spacer rows, sticky headers, border handling, and scroll-anchor handling are directl…
Full details: Description check

Explanation

The description includes the required Changes, Checklist, and Release Impact sections. It explains the motivation, implementation details, testing results, and why pnpm run test:pr was not run. The unchecked test requirement is documented with related checks and an unrelated failure on main.

Full details: Linked Issues check

Explanation

The active directly linked issue is #585. The React example now renders top and bottom spacer rows from the virtual range, removes translated rows and the fixed-height wrapper, and keeps the table sized to the virtualized content. The React CSS adds a sticky header with a background, collapsed borders, and disabled scroll anchoring. These changes address the sticky-header and row-border requirements in #585. The PR summary also reports automated browser checks at multiple scroll positions, including the end of the table.

Full details: Out of Scope Changes check

Explanation

The changes to Vue, Svelte, and Angular apply the same table-sizing fix to equivalent virtual table examples. Their spacer rows, sticky headers, border handling, and scroll-anchor handling are directly connected to the #585 defect pattern. The updated explanatory text supports the changed implementation. No unrelated published code or unrelated feature changes are shown, and the Marko example remains unchanged.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. (4 skipped: 4 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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.

The react table example doesn't make the <table> element large enough

1 participant