Skip to content

fix(site/src/pages/AgentsPage): fix scroll-to-bottom pin starvation in agents chat#23778

Merged
mafredri merged 1 commit intomainfrom
mafredri/fix-safari-scroll-jump
Mar 30, 2026
Merged

fix(site/src/pages/AgentsPage): fix scroll-to-bottom pin starvation in agents chat#23778
mafredri merged 1 commit intomainfrom
mafredri/fix-safari-scroll-jump

Conversation

@mafredri
Copy link
Copy Markdown
Member

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:

  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.

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 cause
of repeated jumps after navigation needs further investigation with Safari
instrumentation.

🤖 This PR was created with the help of Coder Agents, and will be reviewed by a human. 🏂🏻

@mafredri mafredri changed the title fix(site/AgentsPage): fix scroll-to-bottom pin starvation in agents chat fix(site/src/AgentsPage): fix scroll-to-bottom pin starvation in agents chat Mar 30, 2026
@mafredri mafredri changed the title fix(site/src/AgentsPage): fix scroll-to-bottom pin starvation in agents chat fix(site/src/pages/AgentsPage): fix scroll-to-bottom pin starvation in agents chat Mar 30, 2026
@mafredri mafredri marked this pull request as ready for review March 30, 2026 11:50
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.
@mafredri mafredri force-pushed the mafredri/fix-safari-scroll-jump branch from da38185 to b483e96 Compare March 30, 2026 12:25
@mafredri mafredri enabled auto-merge (squash) March 30, 2026 12:26
@mafredri mafredri merged commit 378f11d into main Mar 30, 2026
25 of 27 checks passed
@mafredri mafredri deleted the mafredri/fix-safari-scroll-jump branch March 30, 2026 12:36
@github-actions github-actions bot locked and limited conversation to collaborators Mar 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants