#19783: fix(ui): prevent chat auto-scroll from fighting user scroll during streaming
app: web-ui
size: S
## Summary
- Replaces the `chatScrollPending` boolean guard with a dual-threshold approach that cleanly separates auto-scroll re-engage (50px) from the "new messages below" indicator (450px)
- Removes the `distanceFromBottom` fallback from `shouldStick` in `scheduleChatScroll` — `chatUserNearBottom` is now the sole authority for whether to auto-scroll
- Adds `skipLoading` option to `loadChatHistory` so post-stream history refresh doesn't flash a loading indicator
## Problem
During agent streaming responses, each token update triggers `scheduleChatScroll` → `scrollTo()` → browser fires scroll event → `handleChatScroll` resets `chatUserNearBottom = true` (using the same 450px threshold as the "should we auto-scroll?" check) → next `scheduleChatScroll` sees user as "near bottom" and scrolls again. This creates a feedback loop that prevents users from scrolling up while a response is streaming.
## Approach
Use two separate thresholds in `handleChatScroll`:
- **`SCROLL_LOCK_THRESHOLD` (50px)**: Controls `chatUserNearBottom`. Kept tight so any deliberate upward scroll immediately disengages auto-scroll, while the browser's own programmatic-scroll events (which land at distance ≈ 0) keep it active.
- **`NEAR_BOTTOM_THRESHOLD` (450px)**: Only controls dismissal of the "new messages below" indicator.
In `scheduleChatScroll`, `shouldStick` is simplified to `effectiveForce || host.chatUserNearBottom` — no distance fallback. This means `handleChatScroll`'s 50px threshold is the single source of truth for auto-scroll behavior.
The `chatScrollPending` flag is removed entirely — it's no longer needed because the tight 50px threshold naturally distinguishes programmatic scrolls (distance ≈ 0) from user scrolls (distance > 50px).
## Test plan
- [ ] Open chat, start a long agent response streaming
- [ ] Scroll up while streaming — viewport should stay where user scrolled
- [ ] "New messages below" indicator should appear
- [ ] Scroll back to bottom — auto-scroll resumes
- [ ] Initial page load still auto-scrolls to bottom
- [ ] Unit tests updated with dual-threshold coverage
---
🤖 [Tackled](https://github.com/aleiby/claude-skills/tree/main/tackle) with [Claude Code](https://claude.com/claude-code)
Most Similar PRs
#20347: fix(webchat): resolve streaming scroll race condition
by ndaemy · 2026-02-18
77.2%
#15110: fix: enable auto-scroll during assistant response streaming
by jwchmodx · 2026-02-13
76.8%
#7522: fix(webchat): auto-scroll when message queue changes
by alsoknownasfoo · 2026-02-02
74.9%
#19754: feat(webchat): add cursor-based pagination to chat.history
by aleiby · 2026-02-18
70.4%
#16020: perf(ui): virtualize chat message list for large conversations
by fagemx · 2026-02-14
67.4%
#8353: fix(ui): display tool calls during webchat streaming
by MarvinDontPanic · 2026-02-03
67.4%
#14966: fix(webchat): preserve user message visibility after chat.send
by BenediktSchackenberg · 2026-02-12
65.7%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
65.1%
#20610: fix: reduce chat history render limit to improve performance Fixes #…
by anandsuraj · 2026-02-19
64.8%
#18824: fix(ui): avoid chat bubble flicker after streaming completes
by cccat6 · 2026-02-17
64.6%