Render streaming assistant rows outside virtualizer - #11153
Conversation
…revent layout jumps Replace the `keepMounted` index-based approach with a direct rendering suffix for active assistant turns. Rows belonging to the streaming turn are partitioned out of the virtualizer and rendered as plain DOM elements, eliminating measurement instability caused by rapidly growing content while preserving virtualized history for completed turns.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Incremental ReviewReviewed changes since New commit: The refactored The updated test ("does not retain an older turn after a newer visible turn") precisely captures the new invariant and the expected partition output is correct. Files Reviewed (2 files, incremental)
Reviewed by claude-4.6-sonnet-20260217 · 242,250 tokens Review guidance: REVIEW.md from base branch |
…t.tsx Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
…st visible turn Simplify partitionRows so that older streaming turns are no longer retained in the direct (non-virtualized) output once a newer turn becomes visible. The lookup now checks only the final row's turn against the direct set, ensuring completed assistant turns move back into the virtualizer immediately when the conversation advances.
Benchmark resultsI benchmarked this PR at The scenario used a long active turn with auto-scroll paused, followed by a queued successor turn. This specifically exercised the handoff where the completed older turn should return to the virtualizer and only the latest assistant turn should render directly.
The partition behavior matched the intended design:
Overall, the PR substantially reduced layout-shift frequency, cumulative shift score, and visible-anchor movement. There was a modest scripting/task-time increase, but no long tasks or observable responsiveness regression. |
* fix(vscode): render streaming assistant rows outside virtualizer to prevent layout jumps Replace the `keepMounted` index-based approach with a direct rendering suffix for active assistant turns. Rows belonging to the streaming turn are partitioned out of the virtualizer and rendered as plain DOM elements, eliminating measurement instability caused by rapidly growing content while preserving virtualized history for completed turns. * Update packages/kilo-vscode/webview-ui/src/components/chat/MessageList.tsx Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com> * fix(vscode): complete direct row ID rename * refactor(transcript-rows): restrict direct partition to only the latest visible turn Simplify partitionRows so that older streaming turns are no longer retained in the direct (non-virtualized) output once a newer turn becomes visible. The lookup now checks only the final row's turn against the direct set, ensuring completed assistant turns move back into the virtualizer immediately when the conversation advances. --------- Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Why
We have recently changed the virtualization strategy to go from "per turn" to "per row" in #11094 and this caused the row being streamed to be virtualized too - Causing display issues as shown in the "Before" video below
Implementation
Replace the
keepMountedindex-based approach with a direct rendering suffix for active assistant turns. Rows belonging to the streaming turn are partitioned out of the virtualizer and rendered as plain DOM elements, eliminating measurement instability caused by rapidly growing content while preserving virtualized history for completed turns.Screenshots / Video
Before
before-row-virt.mov
After
after-row-virt.mov
Testing