fix(site/src/pages/AgentsPage): fix scroll-to-bottom pin starvation in agents chat#23778
Merged
fix(site/src/pages/AgentsPage): fix scroll-to-bottom pin starvation in agents chat#23778
Conversation
DanielleMaywood
approved these changes
Mar 30, 2026
scheduleBottomPin() cancelled any in-flight pin and restarted the double-RAF chain on every ResizeObserver notification. When content height changes on consecutive frames (e.g. during streaming where SmoothText reveals characters each frame and markdown re-rendering occasionally changes block height), the inner RAF that actually sets scrollTop is perpetually cancelled before it fires. The scroll falls behind the growing content. Two fixes: 1. Make scheduleBottomPin() idempotent: if a pin is already in-flight, skip. The inner RAF reads scrollHeight at execution time so it always targets the latest bottom. User-interrupt paths (wheel, touch) still cancel via cancelPendingPins(). 2. Add overscroll-behavior:contain to the scroll container. Prevents elastic overscroll from generating extra scroll events that could flip autoScrollRef to false.
da38185 to
b483e96
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
scheduleBottomPin() cancelled any in-flight pin and restarted the double-RAF
chain on every ResizeObserver notification. When content height changes on
consecutive frames (streaming with SmoothText + markdown re-rendering), the
inner RAF that sets scrollTop is perpetually cancelled before it fires.
Proved via a frame-pipeline simulation that models the browser spec ordering
(RAF callbacks -> layout -> ResizeObserver callbacks): with the original
cancel-and-reschedule pattern, the pin never executes while content grows.
With the idempotent version, it fires every 2 frames.
Two fixes:
Make
scheduleBottomPin()idempotent. If a pin is already in-flight,skip. The inner RAF reads
scrollHeightat execution time so it alwaystargets the latest bottom. User-interrupt paths (wheel, touch) still
cancel via
cancelPendingPins().Add
overscroll-behavior: containto the scroll container. Preventselastic overscroll from generating extra scroll events that could flip
autoScrollRefto false.The idle-after-chat-switch jumping is not addressed here. The initial mount
pin uses the same
scheduleBottomPin()so fix #1 helps, but the root causeof repeated jumps after navigation needs further investigation with Safari
instrumentation.