Skip to content

Fix dashboard overflow on shorter terminal heights#18

Merged
programmersd21 merged 3 commits into
programmersd21:mainfrom
CMS-20:fix/resize-overflow
Jul 7, 2026
Merged

Fix dashboard overflow on shorter terminal heights#18
programmersd21 merged 3 commits into
programmersd21:mainfrom
CMS-20:fix/resize-overflow

Conversation

@CMS-20

@CMS-20 CMS-20 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • effectiveViewMode() chose Hero/Compact/Mini using fixed height thresholds (e.g. height >= 22 for Hero) that didn't match how many lines renderDashboard actually produces (28-37 lines depending on mode/height). When the real terminal was shorter than that, the terminal itself scrolled the output, clipping the top of the TUI (title/graphs) while the footer stayed visible — the dashboard never adapted below a certain size.
  • Replaced the static thresholds with a measurement-based pick: render each candidate mode and choose the largest one whose actual line count fits the current terminal height, so the mode selection can't drift out of sync with the layout again.
  • Added a safety clamp in centerFrame so output can never exceed the terminal height even in edge cases, trimming the tail (footer/hints) instead of relying on terminal scroll to hide overflow from the top.

Test plan

  • go build ./...
  • go vet ./...
  • go test ./...
  • Added internal/ui/resize_test.go, a regression test that renders the dashboard across a grid of widths/heights and fails if any combination exceeds the terminal height. Verified it fails against the pre-fix code (reproducing the exact reported bug) and passes with the fix.
  • Built the binary and manually confirmed shrinking a real terminal window now degrades the layout instead of clipping content.

Summary by Sourcery

Adjust dashboard view mode selection and frame centering to prevent terminal overflow and clipping on short terminal heights.

Bug Fixes:

  • Ensure dashboard selects the richest view mode that fits within the current terminal height based on actual rendered line count.
  • Clamp centered frame output to never exceed the terminal height, trimming footer content instead of relying on terminal scroll.

Tests:

  • Add regression test verifying the dashboard never renders more lines than the terminal height across a grid of widths and heights.

Summary by CodeRabbit

  • Bug Fixes
    • Dashboard views now adapt more reliably to terminal size changes, avoiding content that exceeds the available height.
    • When content is too tall, the display now trims from the bottom instead of cutting off the top.
    • View selection now uses the actual rendered content size, improving mode choice for small terminal windows.

effectiveViewMode() picked Hero/Compact using fixed height thresholds
(e.g. height >= 22 for Hero) that no longer matched how many lines
renderDashboard actually produces (28-37 lines depending on mode and
terminal height). When the real content was taller than the terminal,
the terminal itself scrolled the output, clipping the top of the TUI
(title/graphs) while the footer stayed visible.

Replace the static thresholds with a measurement-based pick: render
each candidate mode and choose the largest one whose actual line
count fits the current terminal height. Also clamp centerFrame's
output to the terminal height as a safety net, trimming the tail
(footer/hints) instead of relying on terminal scroll to hide overflow
from the top.

Adds a regression test that renders the dashboard across a grid of
widths/heights and fails if any combination exceeds the terminal
height; it reproduces the original bug when run against the old code.
@CMS-20 CMS-20 requested a review from programmersd21 as a code owner July 6, 2026 22:28
@sourcery-ai

sourcery-ai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR replaces hardcoded height thresholds with measurement-based mode selection for the dashboard, ensures the centered frame never exceeds terminal height, and adds a regression test to guarantee the UI adapts correctly to smaller terminals without clipping the top content.

Sequence diagram for measurement-based dashboard view mode selection

sequenceDiagram
    actor User
    participant Terminal
    participant Model
    participant dashboardLineCount
    participant renderDashboard

    User->>Terminal: resize
    Terminal->>Model: updateSize(width, height)
    Terminal->>Model: effectiveViewMode
    Model->>Model: build candidates
    alt height > 0
        loop for each mode in candidates
            Model->>dashboardLineCount: dashboardLineCount(model, mode)
            dashboardLineCount->>renderDashboard: renderDashboard(model, mode)
            renderDashboard-->>dashboardLineCount: dashboard string
            dashboardLineCount-->>Model: line count
            Model->>Model: [line count <= height]
        end
        Model-->>Terminal: selected mode or ViewTiny
    else height <= 0
        Model-->>Terminal: first candidate mode
    end
Loading

File-Level Changes

Change Details Files
Make dashboard view mode selection depend on actual rendered line count instead of static height thresholds.
  • Introduce a candidate view-mode list that changes based on terminal width.
  • Replace height-based conditional logic in effectiveViewMode with a loop that picks the richest mode whose rendered height fits within the current terminal height.
  • Fallback to tiny mode if no candidate fits and to the first candidate when height is unknown.
internal/ui/model.go
Expose the dashboard’s rendered line count and clamp frame rendering to terminal height.
  • Add dashboardLineCount helper that computes line count by rendering the dashboard and counting newline characters.
  • Update centerFrame to truncate excess lines from the bottom if content exceeds the terminal height, preserving the top rows.
  • Ensure centerFrame still pads content up to the terminal height when it is shorter.
internal/ui/views.go
Add a regression test that validates the dashboard never renders more lines than the terminal height across a grid of sizes.
  • Create TestViewNeverExceedsTerminalHeight which sweeps a range of widths and heights.
  • Instantiate a Model with realistic tracker/history fields for each size combination.
  • Assert that the rendered view’s line count never exceeds the specified terminal height and that the test fails against the old behavior and passes with the fix.
internal/ui/resize_test.go

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai 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.

Hey - I've left some high level feedback:

  • The new effectiveViewMode now renders the dashboard up to three times per view to measure height; consider extracting a lightweight layout-height calculation or caching the rendered height to avoid repeated full renders on every refresh.
  • Using strings.Count(renderDashboard(...), "\n") + 1 in dashboardLineCount assumes there is always at least one line and no trailing newline; if renderDashboard ever changes to include a trailing newline or return an empty string, the line count logic may become inaccurate, so it may be worth enforcing or documenting this invariant.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `effectiveViewMode` now renders the dashboard up to three times per view to measure height; consider extracting a lightweight layout-height calculation or caching the rendered height to avoid repeated full renders on every refresh.
- Using `strings.Count(renderDashboard(...), "\n") + 1` in `dashboardLineCount` assumes there is always at least one line and no trailing newline; if `renderDashboard` ever changes to include a trailing newline or return an empty string, the line count logic may become inaccurate, so it may be worth enforcing or documenting this invariant.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@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 replaces hardcoded height thresholds with a dynamic view-mode selection based on the actual rendered height of the dashboard, and adds a regression test to ensure the layout fits the terminal. However, the review identifies a critical bug: because the rendering pipeline forcefully truncates the output to the terminal height, the line-count check will always evaluate to true, rendering the dynamic mode selection ineffective and causing the regression test to pass falsely. Additionally, rendering the dashboard multiple times per frame introduces a significant performance overhead. It is recommended to implement a lightweight, mathematical line-count calculation and update the test to assert the expected view mode directly.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread internal/ui/views.go Outdated
Comment thread internal/ui/resize_test.go Outdated
Gemini Code Assist correctly flagged that dashboardLineCount measured
renderDashboard's already-clamped output, so every candidate mode
looked like it fit (centerFrame's safety net truncates to terminal
height regardless of mode) and effectiveViewMode always picked Hero,
silently relying on truncation instead of actually adapting. Fix it
by measuring the pre-clamp content height directly.

A second, self-inflicted bug surfaced while fixing the first: an
earlier version of this measurement used len(contentLines) as the
line count, but panel elements are single strings with embedded "\n"s
(a bordered panel is one slice element, not one per row), which
undercounted badly (12 vs. the real ~28). Fixed by counting real
newlines in the joined content instead.

Added TestEffectiveViewModeFitsBeforeClamping, which measures the
pre-clamp content directly (not via dashboardLineCount, so it still
catches a regression in that helper itself) and would have failed
against both of the above. Verified it fails on the old code and
passes now.

Also addresses Sourcery's performance note: introduced
pickViewModeAndContent, which builds each candidate's content once
during mode selection and returns the winning mode's lines directly,
so View() no longer re-renders the chosen mode from scratch a second
time. Removed the now-dead renderHero/renderCompact/renderMini/
renderDashboard wrappers.
@CMS-20

CMS-20 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Thanks both — @gemini-code-assist's catch was correct and important: dashboardLineCount was measuring renderDashboard's already-clamped output, so every candidate mode looked like it fit (the centerFrame safety net truncates to terminal height regardless of mode), and effectiveViewMode was silently always picking Hero and relying on truncation instead of actually adapting.

Pushed a fix that measures the pre-clamp content height directly instead. While fixing it I introduced (and caught, via a test written specifically to make this class of bug fail loudly) a second miscount: an intermediate version used len(contentLines), but panel elements are single slice entries with embedded "\n"s rather than one entry per row, which undercounted badly. Fixed by counting real newlines in the joined content.

Added TestEffectiveViewModeFitsBeforeClamping, which deliberately measures content independently of dashboardLineCount (via dashboardContentLines + its own line-counting) so it still catches a regression in that helper itself, not just in effectiveViewMode's use of it. Confirmed it fails against the original code and passes now.

Also took @sourcery-ai's performance note: added pickViewModeAndContent, which builds each candidate's content once while searching and returns the winning mode's lines directly, so View() no longer re-renders the chosen mode from scratch a second time. Removed the now-dead renderHero/renderCompact/renderMini/renderDashboard wrappers.

@programmersd21 programmersd21 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

nice

add gemini suggestion

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@programmersd21 programmersd21 merged commit 7c3ad54 into programmersd21:main Jul 7, 2026
1 check passed
@programmersd21

Copy link
Copy Markdown
Owner

tysm @CMS-20 !

@programmersd21

Copy link
Copy Markdown
Owner

@coderabbitai

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@programmersd21 Looks like your message got cut off — I don't see a specific question or request attached to the mention. Could you let me know what you'd like help with? For example, I can:

  • Review the latest changes on this PR (@coderabbitai review)
  • Answer questions about the effectiveViewMode/centerFrame fix or the new resize_test.go
  • Help with anything else related to this PR

Just follow up with the details and I'll take it from there!

(=^・ω・^=)

@programmersd21

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d22d4aea-f3ad-45fc-96e1-47ea3e714b56

📥 Commits

Reviewing files that changed from the base of the PR and between 0b15eca and e011428.

📒 Files selected for processing (3)
  • internal/ui/model.go
  • internal/ui/resize_test.go
  • internal/ui/views.go
 _________________________________
< Winner winner, bug-free dinner. >
 ---------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
🧪 Generate unit tests (beta)

❌ Error creating Unit Test PR.

  • Create PR with unit tests
  • Commit unit tests in branch fix/resize-overflow

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

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Note

Unit test generation is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

❌ Failed to create PR with unit tests: AGENT_CHAT: Failed to open pull request

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