fix(tui): correct the v5 UI where real use disagreed with the mock#150
Merged
Conversation
The Redesign v5 tokens were a 10-step hex grey ramp drawn against a #08080a mock and hardcoded. Measured against a translucent terminal (effective background lifted to ~#2b4247 by the wallpaper behind it), the bottom half of that ramp collapsed into the background: cDim3 #3f3f46 -> 1.0:1 cDim2 #52525b -> 1.4:1 cDim4 #3a3a41 -> 1.1:1 cFaint #2e2e34 -> 1.3:1 1.0:1 is the background's own luminance — no terminal can draw that as visible text. Pending pipeline rows, sidebar counts and the status-bar key hints were simply gone. (Rolling back would not have helped: v0.63's own greys measure 1.1:1 / 1.4:1 / 1.9:1 on the same terminal. It only looked better because it left most text at the terminal's default foreground — which is exactly the property being restored here.) The text ramp is now the terminal's own ANSI palette (15 emphasis / 7 body / 8 decorative), which the user's theme guarantees is legible against the background they actually chose. Brand and status hues stay hex — they measure 4.4-6.1:1 on the same terminal and they're the product's identity. Two follow-ons from the same rule: - pipeline rows keep a readable label; the glyph and its hue carry the state. A label faded toward the background reads as missing, not as pending. - hover uses reverse video instead of a painted background. Any colour we picked would be a guess about theirs; the design's #3d3d4a sat at 1.2:1, so the highlight was a no-op exactly where it was needed. A test pins the ramp to ANSI indices so a hex grey can't creep back in.
The v5 redesign unified the scattered planning prompts into one full-screen flow — that part was right, and stays. It then carried on and made the *apply* full-screen too, which was wrong: an alt-screen install takes its own output with it when it exits. Measured on a real run: 24 lines of live install detail on screen, and after the program exits, a blank terminal. Twenty minutes and forty-eight packages, and the only remaining trace of which three failed is a log file. The footer's "everything is logged to ~/.openboot/logs" was not a convenience — it was the design apologising for having thrown the record away. openboot is a command you run once per machine, not an app you live in; its output belongs in the scrollback, where it can be scrolled back, copied into an issue, and piped. So the wizard now stops at the plan. Confirm returns the reviewed InstallPlan, the alt-screen tears down, and the CLI applies it via installer.ApplyReviewedPlan on the normal terminal — ConsoleReporter and the sticky progress bar, which pins the current package to the bottom while results scroll past above it. Live progress and a permanent record, which is what the pre-v5 flow got right. Falling out of it, all of which were alt-screen workarounds: - plan.Silent is no longer forced on. It only existed to keep huh prompts from painting over the TUI, and it gated out the npm-retry confirm and the screen-recording reminder as collateral. They work inline again. - post-install runs in place as Step 8 with its own preview and confirm. splitPostInstall / RunPostInstallAfterTUI are gone. - ShowScreenRecordingReminderAfterTUI is gone: showCompletionFromPlan already does it, and now it's reached. - the "What was installed" breakdown is back. The wizard's log dropped Header/Info lines, so it had never been visible there. - RunPipeline, PhasesForPlan, PlanForConfig and the whole progress-event bridge (~650 lines) are gone with the screen they fed. The wizard no longer imports the install engine at all — only brew/npm's read-only probes for the boot scan. StickyProgress keeps the abort lifecycle the wizard had earned, instead of reverting to its old os.Exit(130) from a signal goroutine: the first ctrl+c stops the bar and lets the cancelled context unwind the install (ApplyContext gates every remaining step on it), and only a second one force-quits — which must stay reachable, because signal.NotifyContext swallows later SIGINTs once it has fired.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two corrections from actually running v0.65.0 in a VM. Both come from the same root cause: the Redesign v5 was drawn as an app against a mock, and openboot is a command that runs in someone else's terminal.
1. The palette assumed a background it didn't have
Reported: on Terminal.app with a translucent background over a wallpaper, pending pipeline rows, sidebar counts, the version and the status-bar key hints were invisible.
Measured, against that terminal's effective background (~
#2b4247):#08080amockcDim3#3f3f46cDim4#3a3a41cFaint#2e2e34cDim2#52525b1.0:1 is the background's own luminance — not "hard to read", impossible to render. Six of twelve ramp tokens were unreadable there.
Worth recording because it was the first instinct: reverting to the v0.63 UI would not have fixed this. v0.63's own greys measure 1.1:1 (
#444), 1.4:1 (#555), 1.9:1 (#666) on the same terminal. It survived by leaving most text at the terminal's default foreground.So the text ramp is now the terminal's own ANSI palette —
15emphasis /7body and anything load-bearing /8decorative — which the user's theme guarantees against the background they actually chose. Brand hues stay hex (4.4–6.1:1 there). Pipeline rows keep a readable label with the glyph carrying the state; hover uses reverse video instead of a background colour we'd have had to guess.2. The install screen destroyed its own output
The v5 redesign unified the scattered planning prompts into one full-screen flow — right, and kept. It also made the apply full-screen — wrong. Measured: 24 lines of install detail on screen, and after the program exits, a blank terminal. The footer's "everything is logged to ~/.openboot/logs" wasn't a convenience; it was the design apologising for throwing the record away.
The wizard now stops at the plan. Confirm returns the reviewed
InstallPlan, the alt-screen tears down, and the CLI applies it on the normal terminal viainstaller.ApplyReviewedPlan—ConsoleReporterplus the sticky progress bar, which pins the current package to the bottom while results scroll into the scrollback. Live progress and a permanent record.What fell out, all of it alt-screen workarounds:
plan.Silentis no longer forced on — it had gated out the npm-retry confirm and the screen-recording reminder as collateralsplitPostInstall/RunPostInstallAfterTUIgone)RunPipeline,PhasesForPlan,PlanForConfigand the progress-event bridge (~650 lines) are gone with the screen they fed; the wizard no longer imports the install engineStickyProgresskeeps the abort lifecycle the wizard had earned rather than reverting toos.Exit(130)from a signal goroutine: first ctrl+c stops the bar and lets the cancelled context unwind (ApplyContextgates every remaining step on it), second one force-quits — which must stay reachable, sincesignal.NotifyContextswallows later SIGINTs once fired.Testing
go vet ./...passesTestTextRampIsTerminalRelativepins the ramp to ANSI indices;TestHoverUsesReverseVideo;TestStickyProgressInterruptIsTwoStage;TestConfigModeConfirmReturnsPlanWithoutInstalling. Install-screen tests were removed with the screen.37m/90m/32mfor text; and after a wizard-confirmed run the banner, the per-step output, the failure and the completion summary are all still on screen once the shell returns (verified with brew off$PATHso nothing installed)Cross-repo checklist
openboot.dev? — worth a look: the install-page copy describing the slug flowNotes for reviewer
The rule both halves encode, now in CLAUDE.md: we don't own the terminal. Don't hardcode a colour that has to contrast with a background we can't see, and don't take over a screen whose scrollback is the user's record. A TUI is right for browsing a 100+ package catalog; it's wrong for a 20-minute apply.