fix(chat): reduce rendering jank during streaming#181
Draft
Conversation
301c968 to
9ea76c5
Compare
The chat view stuttered during streaming responses due to several compounding issues: transition-all on the message container animated height changes as messages grew, smooth scroll was interrupted on every streaming chunk before the previous animation completed, the scrollend listener used anonymous functions so cleanup never matched and broke user scroll-away detection, and the URL regex /g flag made it stateful across split/test calls causing link flicker. Sending a message now always scrolls to bottom and re-enables auto-scroll so the agent response stays visible.
9ea76c5 to
4210bd4
Compare
Messages were reset to [] every time the EventSource reconnected, including on transient network errors. This blanked the entire conversation. Now we let the browser handle SSE reconnection natively and never clear the message list. Also removes the draft filter in sendMessage's finally block which caused the user's message to briefly disappear before the server confirmed it. Drafts are now replaced inline when the matching confirmed message arrives via SSE, and cleaned up on send failure.
4210bd4 to
5035423
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
The chat view had several compounding issues causing visible jank during streaming and full conversation clears on network blips.
The scroll logic used three refs, a
scrollendlistener, and multiple heuristics that fought each other. Thescrollendlistener used anonymous arrow functions, soremoveEventListenernever matched and cleanup never ran. This leftisProgrammaticScrollRefstucktrue, preventingisAtBottomReffrom updating on user scroll events. The user could never scroll away to read earlier context.transition-all duration-300on the message container animated height changes during streaming, creating wobbly layout. The URL detection regex used a/gflag, making it stateful acrosssplit/testcalls and causing links to flicker between renders.Replaced the scroll machinery with direct
scrollTopassignment gated on a singleisAtBottomref updated unconditionally on every scroll event. This runs inuseLayoutEffectbefore paint, avoids animation conflicts, and respects user scroll position. Sending a message always scrolls to bottom and re-enables auto-scroll so the agent response stays visible.Separately,
setMessages([])ran on every SSE reconnect, blanking the conversation on any network blip. Manual reconnect logic inonerroralso fought the browser's built-in SSE reconnection. Thefinallyblock insendMessagefiltered out all draft messages, briefly removing the user's message before the server confirmed it.Now the browser handles SSE reconnection natively, the message list is never cleared, and drafts are replaced inline when the confirmed message arrives. Failed sends clean up their draft in the error paths so ghost messages don't linger.