Skip to content

fix(tui): v3 system stats — fix garbled rendering - #993

Merged
namastex888 merged 1 commit into
devfrom
fix/tui-system-stats-v3
Apr 2, 2026
Merged

namastex888 merged 1 commit into
devfrom
fix/tui-system-stats-v3

Conversation

@namastex888

Copy link
Copy Markdown
Contributor

Summary

Fixes all rendering bugs from v2 system stats (#990):

  • Text overlap: every line wrapped in <box height={1}> (proven TreeNodeRow pattern)
  • Unicode corruption: ASCII [===-----] bars instead of █░▒▓
  • 84-span heatmap: replaced with top-3 hot cores text
  • RAM wrong: uses si.mem().active (excludes buffers/cache)
  • Load nonsense: humanized as 28% (24/84 busy)
  • Version missing: renders immediately before stats load

Test plan

  • 1787/1787 tests pass
  • Lint/format clean
  • Visual QA after merge + update

- Every line uses <box height={1}> (fixes text overlap / "CPUie23%")
- ASCII bar [===-----] instead of Unicode blocks (fixes width corruption)
- Top-3 hot cores replaces 84-span heatmap (readable, meaningful)
- RAM uses si.mem().active (excludes buffers/cache)
- Load humanized as "28% (24/84 busy)"
- Version renders before stats load
@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 849f56b2-98e9-4ee2-9c95-9aece1f42235

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tui-system-stats-v3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the SystemStats component by simplifying the system information interfaces and replacing the per-core heatmap with a list of the top three busiest cores. It also transitions the progress bar to a safe ASCII format and updates the layout using fixed-height boxes. Review feedback suggests defining a constant for the hardcoded bar width, using a more compact format for the 'hot cores' string to avoid TUI truncation, and adjusting the swap usage color to maintain a muted visual hierarchy for low usage.

}

/** Safe ASCII progress bar: [===-----] */
function bar(percent: number, width: number): string {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The bar width 8 is used as a hardcoded value in multiple places (lines 133, 146, 153). It would be better to define a constant (e.g., const BAR_WIDTH = 8;) to ensure consistency and make it easier to update the layout globally.

for (let i = 0; i < cpu.cores.length; i += COLS) {
coreRows.push(cpu.cores.slice(i, i + COLS).map((load, ci) => ({ ...coreChar(load), id: i + ci })));
}
const hotStr = cpu.hotCores.map((c) => `#${c.id} ${c.load}%`).join(' ');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The current hotStr format (e.g., #10 100% #11 100% #12 100%) combined with the ' hot ' prefix can exceed 30 characters. Since the sidebar width is approximately 24-25 characters and the line is constrained by height={1}, it will likely be truncated. A more compact format would ensure the information fits within the TUI layout.

Suggested change
const hotStr = cpu.hotCores.map((c) => `#${c.id} ${c.load}%`).join(' ');
const hotStr = cpu.hotCores.map((c) => `${c.id}:${c.load}%`).join(' ');

<box height={1} width="100%">
<text>
<span fg={palette.textMuted}>SWP </span>
<span fg={pickColor(swap.percent)}>{`${swap.usedGB}/${swap.totalGB}G ${bar(swap.percent, 8)}`}</span>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The use of pickColor for swap usage changes the color from palette.textDim (muted) to palette.emerald (bright green) for low usage. Since swap is ideally empty, using a bright color for 0% usage adds unnecessary visual prominence. Consider using a muted color for low swap usage to maintain the previous visual hierarchy.

Suggested change
<span fg={pickColor(swap.percent)}>{`${swap.usedGB}/${swap.totalGB}G ${bar(swap.percent, 8)}`}</span>
<span fg={swap.percent > 50 ? pickColor(swap.percent) : palette.textDim}>{`${swap.usedGB}/${swap.totalGB}G ${bar(swap.percent, 8)}`}</span>

@namastex888
namastex888 merged commit 14f617b into dev Apr 2, 2026
6 checks passed
@namastex888
namastex888 deleted the fix/tui-system-stats-v3 branch April 10, 2026 16:18
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