Skip to content

fix(chat): stabilize layout and cursor during stream rendering - #1362

Open
Totopo27 wants to merge 1 commit into
vastsa:mainfrom
Totopo27:fix/chat-streaming-jump
Open

Totopo27 wants to merge 1 commit into
vastsa:mainfrom
Totopo27:fix/chat-streaming-jump

Conversation

@Totopo27

@Totopo27 Totopo27 commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Problem / 问题

In v0.16.0, during assistant response streaming, the message layout visibly jumps, shakes, and reflows vertically (reported in #1345).

Root Causes

  1. Cursor presence flapping: showCursor was calculated as displayContent.length < (message.content || "").length. Because chunk tokens arrive in network bursts and the typewriter loop drains at 60–120 fps, the buffer repeatedly caught up with the current source length between packet bursts. This caused the cursor element to toggle on and off multiple times per second during active streaming.
  2. List cursor line-breaking: The selector .assistant-turn-fragment.smooth-cursor .prose-chat > :last-child::after placed the cursor pseudo-element directly under the container <ul> or <ol>. In CSS layout, an inline-block child inside a block list container forces an extra line box after the list items. Each time the cursor toggled on/off, an entire ~20px line was added and removed below the list, repeatedly resizing the container and triggering follow scroll jitter.
  3. Line-wrapping rebalancing during streaming: .prose-chat applies text-wrap: pretty. Chromium's orphan-prevention algorithm repeatedly recalculates line breaks across up to four lines backward as each token or cursor width changes, causing previous lines to reflow and bounce vertically.

Fix / 修复

  1. Keep cursor steady during active stream: In AssistantTurnParts.tsx, maintain showCursor active while streaming (streaming && enabled && Boolean(displayContent)), letting CSS smooth-stream-blink handle the cursor blinking naturally without coupling presence to network packet arrival intervals.
  2. Anchor cursor to inline leaf elements & list items: Target the last li (or its inner trailing element) rather than the list container itself, preventing orphan line-box generation under lists, blockquotes, and code blocks.
  3. Stabilize line wrapping while streaming: Apply text-wrap: wrap on .assistant-turn-fragment.streaming .prose-chat so earlier lines stay locked in place as tokens stream in. Once streaming completes, the .streaming class is removed and text-wrap: pretty formats the final settled message.
  4. Automated tests: Added regression suite in apps/desktop/test/chat-streaming-layout.test.mjs covering cursor presence stability, leaf element placement, and stream text-wrap stabilization.

Fixes #1345

Prevent vertical layout jumping and reflow during assistant stream
rendering by keeping the smooth-stream cursor active throughout active
streaming, positioning the cursor inline at leaf elements and list
items rather than container lists, and disabling orphan-rebalancing
line wrapping during active streams.

Fixes vastsa#1345

This branch was previously deployed

1 inactive deployment
Preview — 9b6b4d7d Deployed Oct 3, 2026 by vercel[bot]
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.

[Bug] Chat content visibly jumps/reflows during streaming in v0.16.0

1 participant