Skip to content

[luv-292] fix: keep virtualizer scrollMargin in sync with layout shifts#292

Merged
NiveditJain merged 1 commit into
mainfrom
luv-292
May 5, 2026
Merged

[luv-292] fix: keep virtualizer scrollMargin in sync with layout shifts#292
NiveditJain merged 1 commit into
mainfrom
luv-292

Conversation

@NiveditJain

@NiveditJain NiveditJain commented May 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Session log viewer was rendering entries at the wrong y-offset, exposing the page --background (#031035) under the empty virtualized container — the "page goes blue while scrolling" symptom.
  • Root cause: app/components/raw-log-viewer.tsx captured useWindowVirtualizer's scrollMargin once in a callback ref reading offsetTop. The ref fires on mount only, so any layout shift above the list (async searchHookActivityAction resolving and mounting <SessionHooksPanel>, Subagents-section / per-subagent collapse-expand, window resize re-flowing StatsBar / ToolStatsGrid) left the value stale. The virtualizer then mapped window scroll → list-local coords with the wrong offset and translated each item by virtualRow.start - staleScrollMargin.
  • Fix: replace the callback ref with a stable useRef<HTMLDivElement> + useLayoutEffect that re-measures via getBoundingClientRect().top + window.scrollY from a ResizeObserver on document.body and a window resize listener. Functional setScrollMargin(prev => prev === top ? prev : top) short-circuits the body-resize feedback the update itself causes.

Test plan

  • bun run lint clean (one pre-existing unrelated warning in tool-input-output.tsx)
  • bunx tsc -p tsconfig.json --noEmit clean
  • bun run test:run — 1452/1452 unit tests pass
  • bun run dev, open a session that has hook activity (so SessionHooksPanel mounts async), scroll mid-list, confirm no blue gap and entries fill the viewport
  • Toggle the Subagents section / individual subagents while scrolled — entries stay aligned, no jump-into-gap
  • Resize window narrower so StatsBar wraps to multiple rows — list stays aligned
  • #entry-<uuid> hash navigation still scrolls to the correct entry

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where log items in the Session log viewer rendered at an incorrect vertical offset when layout shifts occurred above the logs. Log positioning now remains accurate during resize and layout changes.

The session log viewer's `useWindowVirtualizer` captured `scrollMargin`
once via a callback ref on the list wrapper's `offsetTop`. The ref only
fires on mount, so any layout change above the list — async hook-activity
panel mounting, subagent collapse/expand, window resize — left the value
stale. The virtualizer then mapped window scroll → list coords with the
wrong offset, positioning each item at the wrong y-offset and exposing
the page `--background` (#031035) under the otherwise empty container,
giving the "page goes blue while scrolling" symptom.

Replace the callback ref with a stable `useRef<HTMLDivElement>` and a
`useLayoutEffect` that re-measures via `getBoundingClientRect().top +
window.scrollY` from a `ResizeObserver` on `document.body` plus a
window resize listener. Functional `setScrollMargin` short-circuits
same-value updates so the body resize the update itself causes can't
loop.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5fd0755e-4616-4d15-9d18-f9809e944068

📥 Commits

Reviewing files that changed from the base of the PR and between 1ace54b and d79bcda.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • app/components/raw-log-viewer.tsx

📝 Walkthrough

Walkthrough

The Session log viewer's scroll margin calculation is refactored from a mount-only callback ref using offsetTop to a stable useRef with useLayoutEffect that dynamically computes the scroll margin via getBoundingClientRect().top + window.scrollY, resynchronized on layout changes via ResizeObserver and window resize events, fixing incorrect vertical offsets during layout shifts.

Changes

Session Log Viewer Scroll Margin Recalculation

Layer / File(s) Summary
Hook & Observer Logic
app/components/raw-log-viewer.tsx
useLayoutEffect replaces callback ref approach; continuously calculates scrollMargin from bounding rect + scroll position, observes document.body with ResizeObserver, listens to window resize, and guards against redundant updates with equality check.
Ref Wiring
app/components/raw-log-viewer.tsx
List wrapper div updated to use ref={listRef} in place of previous listCallbackRef.
Documentation
CHANGELOG.md
Unreleased fix entry documents the new stable ref + useLayoutEffect flow with guard pattern and resulting behavior fix for misaligned log item offsets.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A scroll margin so fine, now dancing in time,
ResizeObserver whispers, the layout's sublime,
No more offset quirks, just bounding rects true,
Logs rest in their place—hooray, the view's new! 🏃‍♂️✨

🚥 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 and specifically describes the main fix: keeping the virtualizer scrollMargin synchronized with layout shifts to resolve the y-offset rendering issue.
Description check ✅ Passed The PR description covers the issue, root cause, fix approach, and test plan. However, the test plan section shows incomplete manual verification steps (unchecked boxes for dev environment testing).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@NiveditJain
NiveditJain merged commit 2497f5d into main May 5, 2026
9 checks passed
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.

1 participant