Skip to content

fix(ui): repair tab-switch ghost text by bumping bubbletea 1.1 → 1.3#47

Merged
fullstackjam merged 2 commits intomainfrom
claude/debug-row-refresh-tap-wdG8N
Apr 22, 2026
Merged

fix(ui): repair tab-switch ghost text by bumping bubbletea 1.1 → 1.3#47
fullstackjam merged 2 commits intomainfrom
claude/debug-row-refresh-tap-wdG8N

Conversation

@fullstackjam
Copy link
Copy Markdown
Collaborator

@fullstackjam fullstackjam commented Apr 22, 2026

What

Root-cause fix for the tab-switch ghost-text bug that PR #45 worked around with tea.ClearScreen. Also removes that now-redundant workaround.

Why PR #45's workaround was incomplete

bubbletea v1.1.0 was written against x/ansi v0.2.3, but Go MVS resolved x/ansi v0.4.2 via lipgloss v1.0.0. Two breaking changes in x/ansi v0.4.x silently broke bubbletea's standard_renderer:

  1. MoveCursor(row, col)MoveCursor(col, row) — arguments swapped. The post-flush "return cursor to last row" call landed the cursor at row=1 instead of row=linesRendered, so the next render's bottom-up EraseEntireLine / CursorUp1 loop could only clear row 1 and left every row below untouched.
  2. EraseEntireDisplay constant changed from \x1b[2J (clear visible screen) to \x1b[3J (clear scrollback only). tea.ClearScreen therefore left the alt-screen buffer untouched, making the PR Clear screen when switching tabs in snapshot editor #45 tea.ClearScreen emit a no-op on the visible frame.

That combination produced the one-row-offset ghost (cirruslabs/cli sticking above the macOS Prefs list after a Taps → Prefs tab switch).

bubbletea v1.3.0 calls ansi.CursorPosition(col, row) and ansi.EraseEntireScreen directly, matching the v0.4+ API. Incremental diff rendering now clears rows correctly, so the forced full repaint from #45 is redundant and removed.

Changes

  • bubbletea: v1.1.0 → v1.3.0 (direct)
  • x/ansi: v0.4.2 → v0.8.0 (indirect, via bubbletea)
  • x/term: v0.2.0 → v0.2.1 (indirect)
  • x/sync: v0.8.0 → v0.10.0 (indirect)
  • internal/ui/snapshot_editor.go: drop the tea.ClearScreen workaround on Tab / Shift-Tab.

lipgloss / huh / bubbles are unchanged.

Testing

  • go vet ./...
  • go build ./...
  • make test-unit (L1)
  • Manual TUI check: ./openboot snapshot → tab through Formulae → Casks → NPM → Taps → macOS Prefs and back; confirm no cirruslabs/cli ghost at tab-switch and no flicker.

Notes for reviewer

  • PR Clear screen when switching tabs in snapshot editor #45's tea.ClearScreen was load-bearing only because of the two ABI mismatches above; with v1.3.0 the renderer handles clearing itself, so removing it returns us to bubbletea's normal incremental-diff rendering (fewer full repaints, less flicker).
  • Follow-up (separate PR): consider bumping huh so it doesn't rely on MVS goodwill for an ansi version compatible with its pinned v0.2.3.

…st text

Root cause of the cirruslabs/cli ghost row on the macOS Prefs tab:
bubbletea v1.1.0 was written against x/ansi v0.2.3, but MVS resolved
x/ansi v0.4.2 via lipgloss v1.0.0. v0.4.2 silently broke two APIs that
v1.1.0's standard renderer depends on:

  1. MoveCursor(row, col) → MoveCursor(col, row) — arguments swapped.
     The post-flush "return cursor to last row" call landed the cursor
     at row=1 instead of row=linesRendered, so the next render's
     bottom-up EraseEntireLine/CursorUp1 loop could only clear row 1.

  2. EraseEntireDisplay constant changed from "\x1b[2J" (clear visible)
     to "\x1b[3J" (clear scrollback only). tea.ClearScreen therefore
     left the alt-screen buffer untouched, making the PR #45 workaround
     a no-op on the visible frame.

bubbletea v1.3.0 calls ansi.CursorPosition(col, row) and
ansi.EraseEntireScreen directly, matching the v0.4+ API. Tab switching
now clears and redraws correctly; the row-one-only erase artefact is
gone at its source.
@github-actions
Copy link
Copy Markdown

👋 Thanks for opening this pull request!

Before merging:

  • Code follows existing patterns in the codebase
  • go build ./... and go vet ./... pass
  • Commit message is clear and descriptive

@fullstackjam will review this soon. Thanks for contributing! 🚀

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

PR #45 forced a full repaint via tea.ClearScreen on Tab/Shift-Tab to
mask a ghost-text bug whose actual root cause was bubbletea v1.1.0
silently miscalling x/ansi v0.4.2's MoveCursor and EraseEntireDisplay
after MVS upgraded the latter via lipgloss. With bubbletea bumped to
v1.3.0 in the previous commit, the renderer uses ansi.CursorPosition
and ansi.EraseEntireScreen directly, so incremental diff rendering
now clears rows correctly.

The forced full repaint is therefore redundant (just extra flicker on
every tab switch). Removing it.
@github-actions github-actions Bot added the ui Terminal UI label Apr 22, 2026
@fullstackjam fullstackjam changed the title Upgrade dependencies to latest versions fix(ui): repair tab-switch ghost text by bumping bubbletea 1.1 → 1.3 Apr 22, 2026
@fullstackjam fullstackjam merged commit d221f66 into main Apr 22, 2026
9 checks passed
@fullstackjam fullstackjam deleted the claude/debug-row-refresh-tap-wdG8N branch April 22, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ui Terminal UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants