Files
sim/apps
Waleed 2c1392e3a0 fix(chat): autoscroll follow-ups — re-engage threshold + keep end-of-turn options in view (#5094)
* fix(chat): align scrollbar/keyboard detach with wheel/touch re-engage threshold

The onScroll detach branch set only stickyRef.current = false, leaving
userDetachedRef false, so a scrollbar-drag or keyboard detach kept the lenient
30px (STICK_THRESHOLD) re-engage threshold instead of the strict 5px
(REATTACH_THRESHOLD) used after wheel/touch. A programmatic virtualizer re-pin
landing within 30px could then snap autoscroll back on right after the user
deliberately scrolled away. Reuse the detach() helper so all detach paths set
userDetachedRef consistently.

* fix(chat): keep end-of-turn options in view after streaming

When a stream ends, the suggested-follow-up options and the actions row (gated
on !isStreaming) mount, but the virtualizer's getTotalSize — which drives the
scroll container's scrollHeight — only catches up a frame or two later via its
ResizeObserver. The single scrollToBottom() on effect teardown therefore landed
on a stale, too-short bottom and the options were clipped behind the input.
(Pre-virtualization this worked because scrollHeight reflected the new rows
immediately.)

Extract the rAF follow loop already used for CSS height animations into a shared
followToBottom(window) helper and run it for a short settle window on teardown,
so the bottom is chased until the virtualizer re-measures. The follow is
self-interrupting — height growth leaves scrollTop where we put it, while a user
scroll moves it up, so it bails the instant the user scrolls and never fights a
real gesture even with listeners torn down.
2026-06-16 09:51:58 -07:00
..