Skip to content

fix(mobile): stop streaming scroll follow from shifting the document layer - #715

Merged
agegr merged 1 commit into
agegr:mainfrom
nannant666:fix/mobile-stream-flicker
Sep 5, 2026
Merged

fix(mobile): stop streaming scroll follow from shifting the document layer#715
agegr merged 1 commit into
agegr:mainfrom
nannant666:fix/mobile-stream-flicker

Conversation

@nannant666

Copy link
Copy Markdown
Contributor

Fixes #714

Summary

On mobile, invoking the keyboard while the agent is streaming made the whole app visibly flash/jump (roughly on every streamed chunk). The live-follow scroll used scrollIntoView() on the messagesEndRef sentinel, which propagates to every scrollable ancestor — including the keyboard-shifted document layer that mobile browsers (WebKit in particular) keep moving while the keyboard is up. This change scrolls the chat container directly, so programmatic follow-scrolls can never touch the document layer.

What changed

  • hooks/useAgentSession.ts: scrollToBottom now calls container.scrollTo({ top: container.scrollHeight, behavior }) on the chat container itself instead of scrollIntoView() on the sentinel; also returns early when the container is missing. Live-follow attach/detach logic, the prompt anchor, and scroll-position restoration are unchanged.
  • components/ChatWindow.tsx: removed the now-unused messagesEndRef sentinel <div> and its destructured ref.
  • hooks/useAgentSession.test.mjs: updated the three structural assertions that matched the old implementation (container-scroll assertions + a doesNotMatch guard against re-introducing scrollIntoView here).

Testing

  • node --experimental-strip-types --test hooks/useAgentSession.test.mjs lib/chat-lazy-load.test.mjs: 37/37 pass
  • Direct consumer suites (ChatWindow.notices, ChatWindow.process-details, MobilePwaLayout, model-scope-startup, model-switching): 15/15 pass
  • Full suite: 843/844 — the single failure (lib/worktree.test.mjs "main and linked worktrees share one canonical project root") also fails on unmodified main in this environment and is unrelated to this change
  • tsc --noEmit: clean; npm run lint: clean
  • Real device (iOS Safari + installed PWA): with this patch, invoking the keyboard during streaming no longer flashes/jumps the app; streaming follow, prompt anchor, and manual scroll-away behavior all still work as before

…layer

On mobile, invoking the keyboard while the agent is streaming made the
whole app visibly flash/jump. scrollIntoView on the messages-end sentinel
propagates to every scrollable ancestor; when the keyboard has shifted
the document layer, each streamed chunk scrolled that layer too, so the
page visibly jumped on every live-follow tick (on top of the composer
riding the keyboard animation).

Scroll the chat container directly via container.scrollTo instead, and
drop the now-unused messages-end sentinel. Live-follow attach/detach
logic, the prompt anchor, and scroll-position restoration are unchanged.

Verified on a real device (iOS Safari + PWA): keyboard invocation during
streaming no longer flashes the app.
@agegr
agegr merged commit be428cf into agegr:main Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mobile: app flashes/jumps when invoking the keyboard while the agent is streaming

2 participants