Skip to content

fix(vscode): keep session header height stable while streaming - #14154

Merged
marius-kilocode merged 6 commits into
mainfrom
fix-top-bar-ui-flicker
Sep 15, 2026
Merged

marius-kilocode merged 6 commits into
mainfrom
fix-top-bar-ui-flicker

Conversation

@marius-kilocode

@marius-kilocode marius-kilocode commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

What Problem This Solves

The session header grew in steps while a turn streamed. The activity timeline only mounted once an assistant part existed, the context bar only mounted once token counts and a model limit resolved, and the token line only mounted once usage resolved. The token line also changed height when async per-model usage arrived and swapped the plain row for a collapsible trigger. Each step pushed the transcript down, so the header visibly skipped during the first seconds of a turn.

Why This Change Was Made

The header rows had independent mount conditions but no reserved space, so partial data produced partial layout.

The graph section now always reserves the height of all three rows, so the header has one constant height whenever it is shown and the transcript does not move. The skeleton rows are loading states only: each one renders while a turn is running, and a row with no data stays empty instead. Without a configured context limit the context row stays empty, as it did before, instead of animating forever.

Reserving the height rather than adding it when the turn starts also preserves the existing invariant in session-dock-stability.spec.ts, where the transcript viewport and the last message position must not move across the working/idle swap. Gating the section on the turn running failed that spec by 85px.

The token row normalization also removes a pre-existing inconsistency: the plain row and the collapsible trigger rendered at different heights (16px vs 28px), which caused a shift even after all data had loaded.

User Impact

The session header settles at its final height as soon as a session has a message, and the timeline, context bar, and token counts fill in place while a turn runs. The transcript no longer moves on a turn boundary. While a turn is running, rows that are still loading show skeleton rows rather than an empty block or a partially drawn header.

Evidence

Skeleton state while the first turn streams (timeline bars, context track, token row):

Session header showing skeleton rows for the timeline, context bar, and token counts

Checks, all run in packages/kilo-vscode:

  • bun run typecheck: 0 errors
  • bun run lint: clean
  • bun run build-storybook: builds
  • bunx playwright test: 127 passed, 18 skipped (the skipped ones are the Linux-only screenshot comparisons)

The new TaskHeader — loading, first turn story renders the skeleton rows with only a user message, giving the visual regression suite a baseline for this state. Its graph section is 85px, with 5 timeline bars, the context track, and 3 token pills.

Limitations: the streaming state was not reproduced in an isolated VS Code self-test because it requires a paid model request. The state in the screenshot comes from normal use.

The header grew in steps as a turn streamed: the activity timeline
appeared, then the context bar, then the token line, which also jumped
height when the async model usage replaced the plain row with a
collapsible trigger. Each step pushed the transcript down.

Show the graph section as soon as the header is visible and keep every
row at its final height, so the timeline, context bar, and token counts
fill in place without moving the transcript.
@kilo-code-bot

kilo-code-bot Bot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (2 files)
  • packages/kilo-vscode/tests/visual-regression.spec.mts
  • packages/kilo-vscode/tests/visual-regression.spec.ts

Incremental pass over commit 6ca8c523 (test(vscode): skip the flaky diff-panel scroll-up baseline). The commit adds agentmanager--diff-panel-scroll-up to the visual-regression SKIP set in both spec files, with a matching explanatory comment. The ID resolves to the existing DiffPanelScrollUp story (title AgentManager), and its behavior is still exercised by the dedicated tests/diff-scroll-preservation.spec.ts test that drives the same story, so removing it from screenshot comparison is a reasonable tradeoff rather than lost coverage. Both spec files were kept in sync, as packages/kilo-vscode/AGENTS.md requires. No source, listeners, timers, or subscriptions were introduced, so no memory leaks found. No new findings in this pass.

Previous Review Summaries (5 snapshots, latest commit 8c22dd4)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 8c22dd4)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (13 files)
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/board-closed-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/board-empty-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/chat-view-agent-manager-completed-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/chat-view-with-messages-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/prompt-rail-many-prompts-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/prompt-rail-wide-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-background-agents-1280-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-background-agents-200-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-background-agents-420-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-single-background-agent-420-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-skeleton-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-with-todos-all-done-chromium-linux.png
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/chat/task-header-with-todos-chromium-linux.png

Incremental pass over commit 8c22dd48 (chore: update kilo-vscode visual regression baselines). The commit only rewrites generated -chromium-linux.png baselines and adds the new task-header-skeleton-chromium-linux.png baseline for the TaskHeader — loading, first turn story; no source files changed, so this pass added no new findings. Screenshot baselines are generated by Linux CI, so they are not reviewed for content here. No memory leaks found: the change introduces no listeners, timers, or subscriptions.

Previous review (commit fdacb1c)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (5 files)
  • .changeset/stable-session-header-height.md
  • packages/kilo-vscode/webview-ui/src/components/chat/ContextProgress.tsx
  • packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx
  • packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx
  • packages/kilo-vscode/webview-ui/src/styles/task-header.css

Previous review (commit 39e935e)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (5 files)
  • .changeset/stable-session-header-height.md
  • packages/kilo-vscode/webview-ui/src/components/chat/ContextProgress.tsx
  • packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx
  • packages/kilo-vscode/webview-ui/src/stories/chat.stories.tsx
  • packages/kilo-vscode/webview-ui/src/styles/task-header.css

Previous review (commit 121b2ab)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/webview-ui/src/components/chat/ContextProgress.tsx 56 Context skeleton never resolves for models with no known context limit (limit === 0), leaving a permanently animating placeholder where the row used to be absent.

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx 296 Timeline and token skeletons can pulse indefinitely for sessions whose assistant parts/token counts never arrive (failed or cancelled first turn, restored user-only session).
packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx 293 New skeleton state has no Storybook story, so the visual-regression suite cannot baseline it.
Files Reviewed (4 files)
  • .changeset/stable-session-header-height.md - 0 issues
  • packages/kilo-vscode/webview-ui/src/components/chat/ContextProgress.tsx - 1 issue
  • packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx - 2 issues
  • packages/kilo-vscode/webview-ui/src/styles/task-header.css - 0 issues

The incremental commit 121b2abd (chore: update kilo-vscode visual regression baselines) changes only generated -chromium-linux.png baselines, so this pass added no new findings. The three findings above were re-verified against the current HEAD and remain unresolved. No memory leaks found: the change adds no listeners, timers, or subscriptions.

Fix these issues in Kilo Cloud

Previous review (commit f77ae0b)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-vscode/webview-ui/src/components/chat/ContextProgress.tsx 56 Context skeleton never resolves for models with no known context limit (limit === 0), leaving a permanently animating placeholder where the row used to be absent.

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx 296 Timeline and token skeletons can pulse indefinitely for sessions whose assistant parts/token counts never arrive (failed or cancelled first turn, restored user-only session).
packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx 293 New skeleton state has no Storybook story, so the visual-regression suite cannot baseline it.
Files Reviewed (4 files)
  • .changeset/stable-session-header-height.md - 0 issues
  • packages/kilo-vscode/webview-ui/src/components/chat/ContextProgress.tsx - 1 issue
  • packages/kilo-vscode/webview-ui/src/components/chat/TaskHeader.tsx - 2 issues
  • packages/kilo-vscode/webview-ui/src/styles/task-header.css - 0 issues

Verified the skeleton geometry against .task-timeline (26px, 12px bars, 4px gap), confirmed task-header.css is imported by chat.css so the new .task-header-skeleton class is available to both webview bundles, and confirmed the token-row min-height normalization (plain row 24px vs trigger 24px). No memory leaks found: the change adds no listeners, timers, or subscriptions.

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash · Input: 56.5K · Output: 7.1K · Cached: 354.2K

Review guidance: REVIEW.md from base branch main

kilo-maintainer Bot and others added 5 commits September 15, 2026 09:14
Review feedback: the skeleton placeholders could persist forever. The
timeline skeleton only cleared once an assistant part arrived, and the
context skeleton never cleared for models without a context limit, so
both kept animating on idle sessions.

Gate the graph section on a running turn or timeline data, and show each
skeleton only while a turn is in flight. Without a context limit the
context row stays hidden, as it did before. Add a Storybook story for
the first-turn loading state so the skeleton rows get a visual
regression baseline.
Gating the graph section on the turn running made the header 85px taller
when a turn started, which moved the transcript on every turn boundary.
session-dock-stability.spec.ts asserts that swap keeps the transcript
still, and it failed on CI.

Render the graph section whenever the header is shown so its height is
constant, and keep the skeletons as loading states that only render
while a turn is running. Rows without data stay empty instead of
animating forever.

Give the TaskHeader stories visible messages, parts, and token counts so
they render the loaded header. Without them the fixtures showed loading
skeletons, which also changed the task-todo-list docs screenshot.
The visual regression job renders this story slightly differently on each
run, so its baseline keeps flipping by a few pixels without any source
change and the auto-update guard fails the job. Its baseline already
changed in earlier baseline-only commits on main.

The story renders only DiffPanel and is unrelated to the session header,
so skip it like the other non-deterministic diff-panel stories.
@marius-kilocode
marius-kilocode merged commit 6a423a3 into main Sep 15, 2026
27 checks passed
@marius-kilocode
marius-kilocode deleted the fix-top-bar-ui-flicker branch September 15, 2026 10:21
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.

2 participants