feat(gui): move the gui toolbar into the tile header as a measured fold - #963
Merged
sahil-noon merged 4 commits intoSep 13, 2026
Merged
sahil-noon merged 4 commits into
sahil-noon merged 4 commits into
Conversation
ashish-kumar-noon
force-pushed
the
260912-lut4-gui-toolbar-header-fold
branch
from
September 12, 2026 21:12
43fec9a to
3cc9815
Compare
Replaces the floating pill with a width-adaptive cluster in the gui tile's header spring. The fold is measured (hidden probe row + ResizeObserver + expand-edge hysteresis) rather than breakpointed, following the top bar's two existing overflow implementations; the pure arithmetic lives in lib/gui-toolbar-fold.ts. Fullscreen now targets the tile, so the header travels into it and the pill is deleted outright. Cluster controls are re-rendered in header chrome as ControlGlyph SVGs, and the gui tile gains a `wm · display` meta chip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015zcfMsAWgTPeicetw212dA
Memory now describes the header measured fold as present truth: the toolbar pill is retired across gui.md and the ui/ sub-domain, with the two-pass reserve, the priority ladder, the overflow panel, rk-gui-toolbar, the mobile top-bar block, tile-targeted fullscreen, the ControlGlyph set and the wm · display meta chip recorded. Indexes regenerated. Also clears the three should-fix findings from review: stale pill references in touched files, transition narration in the gui-toolbar docblock, and the resolution-menu row mapping duplicated between the size chip's menu and the overflow panel (now one shared helper). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015zcfMsAWgTPeicetw212dA
… by 2px The header-fold conversion turned every glyph-only control into an SVG, which was too broad. Three of them were never glyphs: - `−` / `fit` / `+` are a stepper, not three icons. Magnifier glyphs put two near-identical lenses either side of a word, where the sign carries the whole message, and `fit` names a mode rather than a direction. All three go back to text; ZoomIn/ZoomOut/ZoomFitGlyph are removed with their last caller. - Send key was drawn as a keyboard, which reads as "the keyboard" rather than "send one chord" — and is indistinguishable from a keyboard glyph at the rendered 14px. It returns to the ⌥ option symbol it carried before. Items are separated by 2px (`mx-[1px]` a side) rather than sitting flush; the probe row measures margins already, so the fold arithmetic is unaffected. `-mr-1.5` on the cluster root cancels the tile header's own 6px gap on that one seam, which otherwise left the pinned block's right side wider than its left. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015zcfMsAWgTPeicetw212dA
ashish-kumar-noon
force-pushed
the
260912-lut4-gui-toolbar-header-fold
branch
from
September 13, 2026 09:57
7051f78 to
56a199c
Compare
A wide gui tile left the cluster hugging the right edge with a large empty spring beside it. It now sits at the header's TRUE midpoint while there is clear air on both sides, and snaps back to right-aligned (today's layout, with the fold) the moment there is not. Centring is decided BEFORE the fold, because the two modes have different budgets: centred, the cluster may only use the symmetric middle (headerWidth - 2*max(leftBlock, rightBlock) - 2*clearance), which is narrower than the spring. Fitting against the wrong budget would place items that then overlap a neighbour. Centring is also required to be FREE. Fitting against the narrower middle would otherwise always "succeed" by folding harder — measured at 860px it cost four controls, at 720px all but one. The decision now compares the centred fold against the right-aligned fold and refuses to centre if it would hide or degrade anything extra. Entering centred mode carries the same one-sided hysteresis the fold already uses; leaving is immediate. Without it the two thresholds chase each other: right-aligning frees width, which unfolds an item, which widens the cluster, which makes centring infeasible again. The pinned block (the `⚙` overflow toggle, and the capture verb that follows) and the frame verbs stay right-aligned in both modes — they are chrome with a fixed home, not content that should move with the cluster. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015zcfMsAWgTPeicetw212dA
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.
@sahil87 — ready for review.
Meta
lut4excludes
fab/,docs/· generated by fab-kit v2.26.4Pipeline: intake ✓ → apply ✓ → review ✓ → hydrate ✓ → ship → review-pr
What this does
Moves the
guitile's session toolbar out of the floating pill and into the tile header as a width-adaptive measured fold. The pill is deleted.The pill overlaid the framebuffer, self-hid 3s after the last interaction, and a fine-pointer viewer only got it back via an invisible 24px hover target at the tile's top edge — while the gui tile's own header had an empty
flex-1spring that the tty tile already fills with kind-specific controls.How it folds
One priority ladder, cut to fit: size → zoom → quality → actions. Labels degrade one step before an item folds (
1920×1080 ▾→1920 ▾,◐ Balanced→◐); whatever doesn't fit goes into a⚙panel that renders only when something actually folded.The fold is measured, not breakpointed — a hidden probe row plus one
ResizeObserver, with the arithmetic in a dependency-freelib/gui-toolbar-fold.ts. This is the third instance of the patternlib/top-bar-overflow.tsandlib/crumb-collapse.tsalready establish, including the latter's one-sided expand-edge hysteresis. The two old constants (TOOLBAR_OVERFLOW_MIN_PX,TOOLBAR_SHORT_LABEL_MAX_PX) can't work in a header, where the budget is tile width minus the name, meta chip, pinned block and layout verbs — each varying independently.Notable
keyboardLock()chaining is untouched.⚙doesn't reserve space for itself when nothing folds). A follow-up keyboard-capture change drops into this slot.ControlGlyphSVGs intop-bar-icons.tsx, matching the adjacent verbs at 14px — previously 11px Unicode text.wm · displaymeta chip on the gui tile (tileMetareturnednullforgui).⚙renders into the top bar beside the switch group.pickGuiActionsmirror; no toolbar-only actions.Verification
npx tsc --noEmitcleanjust test-frontend— 223 files / 4628 testsjust test-e2e—gui-toolbar-fold4/4 (real measured widths),gui-surface24/24 incl. the live Xvnc rig, plus a 13-spec adjacent sweepjust test-backend— 37 packages ·just buildOKsurface-focus-chordshas 3 failures that reproduce identically on the pre-change baseline (code-iframe focus race) — pre-existing, not a regressionDesign rationale, rejected options and the interactive fold demo are in
docs/wiki/gui-toolbar-header-studies.html(and-exploration.html), both indexed indocs/specs/index.md.🤖 Generated with Claude Code
https://claude.ai/code/session_015zcfMsAWgTPeicetw212dA