Skip to content

fix: smooth horizontal scrolling in wide data tables - #1544

Merged
sorenbs merged 2 commits into
mainfrom
fix/1476-horizontal-scroll
Jul 18, 2026
Merged

fix: smooth horizontal scrolling in wide data tables#1544
sorenbs merged 2 commits into
mainfrom
fix/1476-horizontal-scroll

Conversation

@sorenbs

@sorenbs sorenbs commented Jul 18, 2026

Copy link
Copy Markdown
Member

Fixes #1476, fixes #1514

Root cause

Three interacting defects in the DataGrid's center-column virtualization:

  1. The virtualization window was derived from scroll event → rAF → setState, re-rendering the whole grid on every scrolled pixel while the mounted column window trailed the real scroll position — outrunning the overscan and producing blank columns and jumpy repaints on wide (large JSON) columns.
  2. The focused-cell auto-scroll effect re-ran on every scroll update whenever the focused cell's element wasn't rendered, writing a column-aligned scrollLeft back toward the focused column — this is the "can never reach the end" / "clicking a cell jumps the viewport back" symptom.
  3. The window was computed from scrollLeft - leftPinnedWidth, shifting it left by the pinned width and under-rendering the right viewport edge.

Fix

  • Compute the window synchronously in the scroll/resize handlers from live scrollLeft/clientWidth; store only the resolved window, and only when it changes — scrolling inside the overscan no longer re-renders the grid.
  • The focused-cell auto-scroll marks itself done up-front (at most once per focus change) so it can never fight user scrolling.
  • Removed the pinned-width subtraction from the window computation.

Verification

  • Reproduced pre-fix and verified post-fix in the live ppg demo on a 61-column table: window follows scrolling to the very end (last column fully rendered at max scrollLeft), focusing a far-right cell leaves scrollLeft untouched, and scrolling away from a focused cell is never yanked back.
  • New regression tests: the auto-scroll fight test fails against the old code (expected 2000 to be 2600); window-update-on-scroll test with rAF stubbed out; end-of-grid window coverage.
  • All 122 grid tests pass; typecheck/lint clean; changeset included.

Note: shares DataGrid.tsx with the smaller pin-reset fix PR (#1371 branch); whichever lands second needs a trivial rebase.

🤖 Generated with Claude Code

Fixes #1476 (duplicate: #1514). Three defects in center-column
virtualization made horizontal scrolling in wide tables jumpy, made the last
column unreachable, and snapped the viewport left when clicking a cell:

- The virtualization window was derived from a raw scroll-position state that
  was updated behind a requestAnimationFrame hop, so every scrolled pixel
  re-rendered the whole grid while the mounted window lagged the real scroll
  position, showing blank columns and jumpy repaints. The window is now
  computed synchronously in the scroll/resize handlers and stored in state
  only when the set of mounted columns actually changes.
- The focused-cell auto-scroll effect re-ran on every scroll update while the
  focused cell's element was not rendered (focused column outside the
  virtualization window, or focused row not on the current page), re-applying
  a column-aligned scrollLeft each time and fighting user scrolling. It now
  runs at most once per focused-cell change and falls back to any rendered
  cell in the focused row for the vertical reveal.
- The window was computed from scrollLeft shifted left by the pinned-column
  width, under-rendering columns at the right viewport edge. Sticky pinned
  columns occupy as much viewport as they occupy row start, so container
  scrollLeft maps 1:1 onto center-column offsets.

Verified in the ppg demo against the 61-column all_data_types table: the
window follows scrolling to the very end, the last column renders fully, and
clicking or focusing cells no longer moves the viewport. Regression tests
cover the auto-scroll fight, animation-frame-free window updates, and
end-of-grid window coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 41 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a3e5ff21-27e7-473d-a15c-d699eec3bbd6

📥 Commits

Reviewing files that changed from the base of the PR and between 310b657 and 5504199.

📒 Files selected for processing (2)
  • ui/studio/grid/DataGrid.interactions.test.tsx
  • ui/studio/grid/DataGrid.tsx

Walkthrough

Updated wide-table column virtualization to compute synchronously from scroll, resize, and layout changes while storing only changed virtualization windows. Added virtualization window constants and equality helpers, corrected maximum-scroll coverage, and adjusted focused-cell auto-scroll to run once per focus change with a rendered-row fallback. Added interaction and virtualization tests plus documentation and a patch changeset.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: smoother horizontal scrolling in wide data tables.
Description check ✅ Passed The description matches the scroll-glitch fix and its verification/tests.
Linked Issues check ✅ Passed The changes address both linked issues by fixing horizontal jumpiness, end-of-grid reachability, and repeated focus-driven auto-scroll.
Out of Scope Changes check ✅ Passed The changes stay within the scrolling fix, regression tests, docs, and changeset; no unrelated scope is evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1476-horizontal-scroll
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/1476-horizontal-scroll

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

@github-actions

Copy link
Copy Markdown
Contributor

Compute preview deployed.

Branch: fix/1476-horizontal-scroll
Service: fix-1476-horizontal-scroll
Preview: https://szrbqj1jjtfugmavxc3fi20d.cdg.prisma.build

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/studio/grid/DataGrid.tsx`:
- Around line 1810-1815: Update the focused-cell auto-scroll effect around
autoScrolledFocusedCellRef so it does not mark a focus change handled until the
container, column, and usable viewport are available. Preserve the
once-per-focus behavior after scrolling is actionable, while allowing hidden or
not-yet-laid-out grids to retry when column/layout readiness changes.
- Around line 1209-1211: Update the centerVirtualizationInputsKey construction
to serialize each column’s id and size as structured tuples, including
leftPinnedWidth and rightPinnedWidth, instead of joining delimiter-based
strings. Ensure distinct column/width inputs always produce distinct keys so
virtualization state is not reused with stale widths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0f043c8e-b2cc-441d-b47f-df0a60fc6b24

📥 Commits

Reviewing files that changed from the base of the PR and between 81354ff and 310b657.

📒 Files selected for processing (8)
  • .changeset/smooth-horizontal-scroll.md
  • Architecture/wide-grid-performance.md
  • FEATURES.md
  • ui/studio/grid/DataGrid.interactions.test.tsx
  • ui/studio/grid/DataGrid.tsx
  • ui/studio/grid/DataGrid.virtualization.test.tsx
  • ui/studio/grid/column-virtualization.test.ts
  • ui/studio/grid/column-virtualization.ts

Comment thread ui/studio/grid/DataGrid.tsx Outdated
Comment thread ui/studio/grid/DataGrid.tsx Outdated
- Serialize the center-column virtualization inputs key structurally with
  JSON.stringify instead of delimiter joining, so column ids containing the
  delimiter characters cannot produce colliding keys.
- Keep a focused-cell auto-scroll pending while its prerequisites are missing
  (no scroll container, unknown column, or an unmeasured/hidden grid) instead
  of marking it handled up-front. Column changes and a new viewport-readiness
  tick re-trigger the effect when layout becomes ready; neither signal changes
  on plain scrolling, so the at-most-once-per-focus guarantee against fighting
  user scrolling is preserved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sorenbs
sorenbs merged commit 6c9e625 into main Jul 18, 2026
3 checks passed
@sorenbs
sorenbs deleted the fix/1476-horizontal-scroll branch July 18, 2026 13:04
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.

Infinite scroll horizontally Horizontal scroll jumps and never ends

1 participant