Skip to content

fix(tui): stabilize dynamic-height UI components to reduce jitter#1365

Open
liruifengv wants to merge 2 commits into
mainfrom
fix/dynamic-ui-height
Open

fix(tui): stabilize dynamic-height UI components to reduce jitter#1365
liruifengv wants to merge 2 commits into
mainfrom
fix/dynamic-ui-height

Conversation

@liruifengv

Copy link
Copy Markdown
Collaborator

Related Issue

N/A — this addresses visual jitter observed during TUI rendering without a prior issue.

Problem

Several TUI components change height during their lifecycle (start tall, then collapse). Because pi-tui re-renders the whole screen, a collapsing component shifts all subsequent content up, producing visible jitter. Examples include the thinking panel finalizing, subagent groups finishing, tool-call progress clearing on result, the todo panel clearing, and the slash-command autocomplete closing.

What changed

  • Added a FixedHeightWindow primitive so components return a stable row count across running/finished transitions.
  • Kept AgentGroup, ThinkingComponent, ShellRunComponent, and the Todo panel at a stable height.
  • Capped ToolCallComponent progress lines to a fixed window and capped the Edit preview at args finalize (with tail mode) so long diffs do not snap on result.
  • Forced a full render when dialogs, the autocomplete dropdown, or the BTW panel close, and when the AgentSwarm panel is removed, to clear scrollback residue.
  • Added tests covering the new height-stability behavior.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill.
  • Ran gen-docs skill, or this PR needs no doc update. (No user-facing doc change.)

Add FixedHeightWindow and stabilize heights of AgentGroup, Thinking, ShellRun, Todo, and ToolCall previews. Force full render on dialog/autocomplete/BTW close and AgentSwarm removal to clear scrollback residue.
@changeset-bot

changeset-bot Bot commented Jul 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fd476e8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 4, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@fd476e8
npx https://pkg.pr.new/@moonshot-ai/kimi-code@fd476e8

commit: fd476e8

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3282ae14fd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +121 to +124
const window = new FixedHeightWindow({
height: RUNNING_TAIL_LINES,
tail: true,
lines: allLines,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep finished shell output accessible

When a ! shell command finishes with more than five lines, this fixed window keeps only the tail. The status line says ctrl+o to expand, but ShellRunComponent does not implement setExpanded, and KimiTUI.toggleToolOutputExpansion() only updates transcript children that pass isExpandable, so the earlier output can no longer be viewed in the TUI; before this change the final view rendered the full formatBashOutputForDisplay output. Please either preserve the full final output or add real expansion support for this component.

Useful? React with 👍 / 👎.

Comment on lines +264 to +267
if (this.wasShowingAutocomplete && !showing) {
// Autocomplete dropdown just closed: the editor returned fewer lines,
// which would pull the footer up and leave stale rows in scrollback.
this.tui.requestRender(true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Move the forced autocomplete redraw out of render

This call runs from inside CustomEditor.render(), while TUI.doRender() is already rendering the frame. requestRender(true) mutates the TUI diff state synchronously (clearing previousLines and changing previous dimensions), so on the ordinary autocomplete-close path the current render can take the first-render/full-frame path without clearing and then overwrite the scheduled forced render state, leaving the intended cleanup ineffective or duplicating the UI. Trigger the forced redraw from the close/input path after the current render instead of mutating TUI state during render.

Useful? React with 👍 / 👎.

Short thinking content (<=2 lines) was padded to a fixed 4-row skeleton, leaving trailing blank rows. Restore natural height for short content while keeping the 4-row shape for long content so live and finalized stay aligned.
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.

1 participant