fix: scrolling up during a running thread no longer snaps back to the bottom - #5566
Conversation
On both web and mobile, scrolling up while a thread streamed would snap back to the bottom on the next chunk. Mobile had no user-scroll latch at all (LegendList's maintainScrollAtEnd re-pinned on pure geometry); web re-armed live-follow within half a viewport of the end and let the library's own maintain re-pin regardless of the app's follow state. Follow now breaks when the user scrolls away and re-arms only when the viewport actually returns to the bottom, on send, or on thread switch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
ApprovabilityVerdict: Approved f7fa313 This is a well-scoped bug fix for scroll behavior that prevents the timeline from yanking users back to the bottom while they're reading history. Changes are self-contained to scroll handling logic across mobile and web, include unit tests for the threshold logic, and have clear explanatory comments. You can customize Macroscope's approvability policy. Learn more. |
Dismissing prior approval to re-evaluate f7fa313
## What's Changed * fix: prevent reconnect loops during server stalls by @gfsaaser24 in pingdotgg/t3code#5561 * fix(server): settle stopped Claude subagents by @t3dotgg in pingdotgg/t3code#5568 * fix: scrolling up during a running thread no longer snaps back to the bottom by @t3dotgg in pingdotgg/t3code#5566 ## New Contributors * @gfsaaser24 made their first contribution in pingdotgg/t3code#5561 **Full Changelog**: pingdotgg/t3code@v0.0.32-nightly.20260807.1020...v0.0.32-nightly.20260807.1021 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.32-nightly.20260807.1021
Scrolling up while a thread was streaming would yank you back to the bottom on the next update, on both web and mobile. You had no way to read earlier messages until the turn finished.
Now scrolling up holds your position, and scrolling back down to the bottom re-enables the stick-to-bottom behavior.
What was wrong:
maintainScrollAtEndre-pinned on pure geometry — anywhere within ~10% of a viewport of the bottom (or any thread shorter than the screen) snapped back on every stream chunk. Added a follow latch: a user drag (through its momentum) that leaves the bottom zone disables the maintain; returning to the bottom, sending, or switching threads re-arms it.isNearEnd, which is true up to half a viewport above the bottom, so a modest scroll-up still counted as "following". The library's own maintain also ran independently of the app's follow state, the escape listeners attached in one animation frame with no retry, and keyboard scrolling never broke follow at all. Follow now re-arms only within a tight band at the true content bottom, gates the library maintain, and the opt-out listeners retry attachment, cover PageUp/Home/ArrowUp, and are direction/position-aware.Browser-verified in Chrome with a live 17-second GPT-5.6-Luna turn: the viewport remained exactly 1,100 px from the bottom through completion, then resumed normal follow after using Scroll to end.
Verified with typecheck, lint, and unit tests on both apps (1821 web, 615 mobile).
🤖 Latest fix generated with GPT-5.6-Sol in T3 Code using the Codex harness.
Note
Medium Risk
Changes core chat scroll-follow behavior on web and mobile during streaming; localized to timeline UX but easy to regress edge cases (keyboard, touch, anchor sends).
Overview
Fixes thread timelines yanking back to the bottom on every stream chunk after you scroll up to read earlier messages. Live follow is now an explicit latch that gates LegendList’s
maintainScrollAtEndinstead of leaving the library to re-pin on its own geometry.On mobile (
ThreadFeed), follow turns off only during a real user drag/momentum that leaves the end band, and turns back on when you return to the bottom, switch threads, or anchor on send. On web (ChatView/MessagesTimeline), aliveFollowEnabledflag does the same gating; opt-out listeners retry if the list isn’t mounted yet, and wheel/touch/pointer/keyboard handlers only break follow when the viewport can actually move away from the live edge (avoiding spurious breaks while still pinned).resolveTimelineIsAtEndno longer treats LegendList’s broadisNearEndas “at end”; it uses a 40px band at the true content bottom (with composer end inset), so modest scroll-up no longer re-arms follow. Send-time anchor positioning is also guarded so remeasures after a turn completes don’t restart anchoring once you’ve scrolled away.Reviewed by Cursor Bugbot for commit f7fa313. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix chat scroll so scrolling up during a running thread no longer snaps back to the bottom
maintainScrollAtEndon a flag rather than always keeping it enabled.resolveTimelineIsAtEndin MessagesTimeline.logic.ts now uses geometry-based evaluation with a 40px (TIMELINE_FOLLOW_REARM_THRESHOLD_PX) re-arm band, replacing the previousisNearEndcheck.Macroscope summarized f7fa313.