Skip to content

Migrate TUI overlays onto the design language (Epic 2.1) - #136

Merged
TraderSamwise merged 2 commits into
masterfrom
chore/tui-overlays-theme
Jun 15, 2026
Merged

Migrate TUI overlays onto the design language (Epic 2.1)#136
TraderSamwise merged 2 commits into
masterfrom
chore/tui-overlays-theme

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Epic 2, phase 1 of the TUI design-language rollout. Migrates the overlay surfaces off hand-written escape codes onto the shared theme primitives from src/tui/render/theme.ts.

  • renderOverlayBox now draws a rounded, tinted modal (info/danger tone) composed from theme tokens, opaque by overwriting each cell, with ANSI-aware content padding (padVisible/visibleWidth).
  • Overlay bodies tokenize titles (strong), secondary text (muted), and render key hints as keycaps via a shared hints() helper.
  • Help and switcher overlays now route through renderOverlayBox instead of hand-rolling their own boxes.
  • Notification panel gains a rounded two-pane tinted border with styled list/detail cells and statusDot read/unread markers.

Behavior preserved

Same triggering conditions, null-return guards, keybindings, and content — purely a presentation migration.

Verification

yarn typecheck, yarn lint, yarn build clean; full suite 1256 tests pass (new box.test.ts).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added test coverage for overlay box rendering with ANSI color and styling validation.
  • Refactor

    • Refactored overlay rendering to use shared theme utilities for consistent styling across TUI overlays.
    • Improved text width calculation and padding handling in overlay displays.
    • Updated overlay parameter naming for clarity.

renderOverlayBox now draws a rounded, tinted (info/danger) modal composed
from theme tokens, opaque by overwriting each cell, with ANSI-aware content
padding. Overlay bodies tokenize titles, dim hints, and render key hints as
keycaps; help and switcher route through the shared box; the notification
panel gets a rounded two-pane border with styled list/detail cells.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jun 15, 2026 11:32am

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@TraderSamwise, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 1 hour, 22 minutes, and 2 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 77d4d35c-99ee-43be-8231-6a7d337f0d5e

📥 Commits

Reviewing files that changed from the base of the PR and between 73976b8 and 46d24b6.

📒 Files selected for processing (1)
  • src/tui/render/box.test.ts
📝 Walkthrough

Walkthrough

renderOverlayBox in box.ts is refactored to use shared theme utilities (visibleWidth, padVisible, style) and rounded border characters, with the style parameter renamed to variant. New Vitest tests cover box characters, color variants, and ANSI body preservation. All overlay builders in overlay-renderers.ts are updated to use a new hints() helper and theme-based styled keycaps, borders, and dividers.

Changes

TUI Overlay Theme Refactor

Layer / File(s) Summary
renderOverlayBox refactor to theme utilities
src/tui/render/box.ts
Replaces inline ANSI stripping/truncation with visibleWidth, padVisible, and style from ./theme.js; adds VARIANT_TONE mapping; renames style param to variant; rewrites border rendering with rounded characters (╭╮╰╯, ).
Vitest tests for renderOverlayBox
src/tui/render/box.test.ts
Adds three test cases: box-drawing character output, ANSI color codes for "blue" and "red" variants, and ANSI-styled body content preservation validated via stripAnsi.
hints() helper and simple overlay refactors
src/tui/screens/overlay-renderers.ts (lines 1–145)
Adds hints() internal helper; converts service input, label input, worktree list, worktree remove confirm, dashboard busy, and dashboard error overlays from raw string key indicators to styled keycaps and structured hint rows.
Notification panel, help, teammate picker, switcher, migrate picker refactors
src/tui/screens/overlay-renderers.ts (lines 160–388)
Overhauls notification panel with statusDot, keycap, padVisible, and styled borders; rewrites buildHelpOverlayOutput with styleHelpLine() delegating to renderOverlayBox; updates teammate picker, switcher, and migrate picker with styled pointer/keycap numbering and structured hints().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • TraderSamwise/aimux#135: Introduces the src/tui/render/theme.ts module with visibleWidth, padVisible, and style primitives that this PR's renderOverlayBox refactor and overlay renderer updates directly depend on.

Poem

🐇 Hop hop, the borders are round now,
╭─ styled with theme ─╮
No more raw ANSI in a tangled heap,
keycap and hints() make the UI neat,
Blue tone, red tone, all sharp and sweet,
Tests confirm what the rabbit drew—
Every box gleams fresh and new! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change—migrating TUI overlays to use a design language system. It directly relates to the changeset's primary focus of refactoring overlays from hand-written escape codes to shared theme primitives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/tui-overlays-theme

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

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
src/tui/render/box.test.ts (1)

23-27: 💤 Low value

Test name implies width verification that isn't actually performed.

The test name mentions "without breaking width," but the assertion only confirms the visible content is present (stripAnsi(out).toContain("bold plain")). To verify width behavior, consider adding an assertion that checks padding/truncation—e.g., verifying the output row length after stripping ANSI matches the expected boxWidth.

That said, the current assertion does validate ANSI preservation which is valuable. Consider either renaming to "preserves ANSI styling in body content" or adding a width-specific check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tui/render/box.test.ts` around lines 23 - 27, The test "preserves ANSI
styling in body content without breaking width" has a name that claims to verify
width behavior, but the only assertion checks content presence via
stripAnsi(out).toContain("bold plain"), not actual width. Either rename the test
to "preserves ANSI styling in body content" to accurately reflect what it tests,
or add an additional assertion that verifies width behavior (e.g., checking that
stripAnsi(out) lines match the expected boxWidth after stripping ANSI codes).
Choose the approach that best reflects the test's primary intent.
src/tui/screens/overlay-renderers.ts (1)

199-201: 💤 Low value

Width constraints can exceed available space on narrow terminals.

When width is small, the minimum bounds (leftWidth ≥ 28, rightWidth ≥ 20) force boxWidth to at least 55 columns regardless of actual terminal width. For a 40-column terminal, this would cause overflow.

Consider capping boxWidth to width or adjusting the minimums relative to available space:

  const leftWidth = Math.max(28, Math.floor((width - 7) * 0.5));
  const rightWidth = Math.max(20, width - 7 - leftWidth);
- const boxWidth = leftWidth + rightWidth + 7;
+ const boxWidth = Math.min(width, leftWidth + rightWidth + 7);

This is an edge case for unusually narrow terminals, so it may be acceptable to defer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tui/screens/overlay-renderers.ts` around lines 199 - 201, The width
calculation in the overlay renderer is causing boxWidth to potentially exceed
the available terminal width on narrow displays. The minimum constraints applied
to leftWidth (28) and rightWidth (20) force a minimum boxWidth of 55 columns,
which can overflow terminals narrower than this. Fix this by either capping the
final boxWidth calculation to not exceed the available width parameter, or by
adjusting the minimum width values (28 and 20) to be relative to and respect the
available space. Ensure that leftWidth, rightWidth, and the resulting boxWidth
remain constrained within the actual terminal width.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/tui/render/box.test.ts`:
- Around line 23-27: The test "preserves ANSI styling in body content without
breaking width" has a name that claims to verify width behavior, but the only
assertion checks content presence via stripAnsi(out).toContain("bold plain"),
not actual width. Either rename the test to "preserves ANSI styling in body
content" to accurately reflect what it tests, or add an additional assertion
that verifies width behavior (e.g., checking that stripAnsi(out) lines match the
expected boxWidth after stripping ANSI codes). Choose the approach that best
reflects the test's primary intent.

In `@src/tui/screens/overlay-renderers.ts`:
- Around line 199-201: The width calculation in the overlay renderer is causing
boxWidth to potentially exceed the available terminal width on narrow displays.
The minimum constraints applied to leftWidth (28) and rightWidth (20) force a
minimum boxWidth of 55 columns, which can overflow terminals narrower than this.
Fix this by either capping the final boxWidth calculation to not exceed the
available width parameter, or by adjusting the minimum width values (28 and 20)
to be relative to and respect the available space. Ensure that leftWidth,
rightWidth, and the resulting boxWidth remain constrained within the actual
terminal width.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f5c540d7-9adf-49ec-9c54-09eb2db13f1e

📥 Commits

Reviewing files that changed from the base of the PR and between 64e5480 and 73976b8.

📒 Files selected for processing (3)
  • src/tui/render/box.test.ts
  • src/tui/render/box.ts
  • src/tui/screens/overlay-renderers.ts

Address CodeRabbit nitpick: the box test now verifies every modal row is
padded/truncated to the same visible width (and within cols), instead of only
checking content presence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TraderSamwise

Copy link
Copy Markdown
Owner Author

Addressed CodeRabbit nitpicks in 46d24b6:

  • box.test.ts: added a width assertion — the test now verifies every modal row is padded/truncated to a uniform visible width and stays within cols (renamed the ANSI-preservation case accordingly).
  • Notification panel min-widths (leftWidth≥28/rightWidth≥20): kept by design. These are sensible minimums; on a terminal too narrow to fit them the panel simply overflows and is clipped by the terminal, same graceful degradation as before (the prior code had an even larger leftWidth≥34 minimum).

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