Skip to content

ui(shell): un-collide the top-right status cluster, tip the transport bar, keep the audio graph out of the clips browser - #353

Merged
jeffcrouse merged 1 commit into
mainfrom
ui-shell-fixes-toolbar-tooltips
Aug 15, 2026
Merged

ui(shell): un-collide the top-right status cluster, tip the transport bar, keep the audio graph out of the clips browser#353
jeffcrouse merged 1 commit into
mainfrom
ui-shell-fixes-toolbar-tooltips

Conversation

@jeffcrouse

@jeffcrouse jeffcrouse commented Aug 15, 2026

Copy link
Copy Markdown
Member

Three shell-chrome defects reported against the running app, plus the geometry test that would have caught two of them.

1. The top-right status cluster collided

The ADR-0019 health rollup dot (layout.h, win_w - 26) and the always-on perf read-out (frame.cpp, right-aligned at win_w - 8) were two independent right-edge anchors, neither aware of the other. The dot's full 12px width landed inside the chip — and because the chip draws last at 0.60 alpha, it read as a green smudge under the fps text rather than a status light.

Both now derive from one gutter constant: health_dot_rect pins to kTopRightPad, and the new perf_hud_rect anchors off it and grows leftward as the string gets longer. Both are vertically centred on the 40px bar, so the cluster reads as one row.

2. No tooltips on the transport bar

There was no tooltip mechanism in the app at all — every control re-derives hov each frame and throws it away, and nothing tracked dwell.

New ui/tooltip.h holds the one piece of state an immediate-mode UI can't recompute: how long the cursor has been on the same item. It reuses hover_status() (the clip/sampler editors' existing "what will happen" pill) as its body rather than introducing a second chrome vocabulary.

session_view::tick_top_bar_tooltip walks the same layout.h rects the draw and the hit-tests use, so a moved control can't leave its tooltip behind. It runs in the frame loop's overlay pass — after the perf HUD (whose text-driven rect it tips) and last of all, so the pill sits above every other overlay. Suppressed over a modal and mid-drag.

Tips carry the cheat-sheet's shortcut letters (Space / R / H). The health dot's also reports its current rollup, so hovering answers "is anything wrong?" without opening the panel.

TipState.anchor is a placement rect, not the hit rect — the transport row passes a common band so the pill doesn't bob as the cursor crosses controls of differing heights.

3. The audio graph painted over the CLIPS browser

audio_graph_pane hard-coded x = kPaneMargin. The session grid escapes this via draw_ui's set_transform(SW,0,1), but that transform and its clip are torn down before the audio graph draws — it runs in raw screen space (and agr.draw sets its own camera, which would clobber the shift anyway), so the offset has to live in the rect.

The pane now takes sidebar_w, exactly as sidebar_panel / pool_item_rect already do. Because prime / ag_pane_hit / on_down share the helper, this also fixes an unreported input bug: scrolling over the CLIPS panel was zooming the audio graph (clicks were saved only by dispatch order).

Not a code defect

The reported "+ Note button still in the visuals graph" was a stale binary — the button was removed in #348 and the running build predated it. No change here.

Tests

New test_shell_layout (pure layout.h, headless) pins both geometry invariants, neither of which a compiler can see:

  • the cluster never intersects, across a spread of window widths x text widths; the chip stays strictly left of the dot; both stay on-screen and share a vertical centre
  • the chip is right-anchored (longer text extends left, never toward the dot)
  • the audio pane is byte-identical to the old geometry when the browser is closed
  • with the browser open it clears the CLIPS panel, still stops short of the splitter, and keeps its vertical span
  • a window narrow enough that the splitter sits left of the sidebar still yields a non-degenerate rect (a negative width would blow up the scissor)

227 checks. Full suite: 100/100.

Verified live

On the blob project, driven with synthetic input:

  • cluster separated and centred
  • all seven tips render at a consistent baseline; the two right-edge tips clamp inside the window
  • browser open → no overlap, CLIPS fully visible
  • scroll over CLIPS is inert (graph layout byte-identical; only the live waveform animates)
  • audio-node clicks still hit correctly at the new offset (dock switches to the node's params)

🤖 Generated with Claude Code

… bar, keep the audio graph out of the clips browser

Three shell-chrome defects reported against the running app, plus the geometry
test that would have caught two of them.

1. Top-right collision. The ADR-0019 health dot (layout.h, win_w-26) and the
   always-on perf read-out (frame.cpp, right-aligned at win_w-8) were two
   independent right-edge anchors, so the dot landed INSIDE the chip — and since
   the chip draws last at 0.60 alpha, it read as a green smudge under the fps
   text. Both now derive from one gutter constant: health_dot_rect pins to
   kTopRightPad and the new perf_hud_rect anchors off it, growing leftward as the
   string gets longer. Both are centred on the 40px bar.

2. No tooltips on the transport bar. New ui/tooltip.h: TipState (the one piece of
   state an immediate-mode UI can't recompute — dwell on the SAME item) plus
   tip_set/tip_clear/draw_tooltip, with hover_status() as the pill body so this
   doesn't introduce a second chrome vocabulary. session_view's
   tick_top_bar_tooltip walks the SAME layout.h rects the draw and hit-tests use,
   so a moved control can't leave its tooltip behind. Runs in the frame loop's
   overlay pass, after the perf HUD (whose text-driven rect it tips) and last of
   all, so the pill sits above every overlay. Suppressed over a modal or mid-drag.
   Tips carry the cheat-sheet's shortcut letters (Space / R / H); the health dot's
   also reports its current rollup, so hovering answers "is anything wrong?"
   without opening the panel.

3. The audio graph painted over the CLIPS browser. audio_graph_pane hard-coded
   x = kPaneMargin. The session grid escapes this via draw_ui's set_transform(SW,0,1),
   but that transform and its clip are torn down before the audio graph draws — it
   runs in raw screen space (agr.draw sets its own camera, which would clobber the
   shift anyway), so the offset has to be in the rect. The pane now takes sidebar_w,
   like sidebar_panel/pool_item_rect already do. This also fixes the input side:
   prime/ag_pane_hit/on_down share the helper, so scrolling over the browser no
   longer zooms the graph (clicks were saved only by dispatch order).

The reported "+ Note button still in the visuals graph" was not a code defect —
it was removed in #348 and the running binary predated it. No change here.

tests: new test_shell_layout pins both geometry invariants (the cluster never
intersects across window/text widths; the audio pane clears an open browser,
is byte-identical when closed, and stays non-degenerate in a narrow window).
227 checks; full suite 100/100.

Verified live on the blob project: cluster separated, all seven tips render at a
consistent baseline and clamp inside the right edge, browser open shows no
overlap, scroll over CLIPS is inert, and audio-node clicks still hit at the new
offset.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Production gate (core): ✅ PASS

  • 83/83 tests passed (0 failed) in 16.453s

@jeffcrouse
jeffcrouse merged commit bc9f7fc into main Aug 15, 2026
8 checks passed
@jeffcrouse
jeffcrouse deleted the ui-shell-fixes-toolbar-tooltips branch August 15, 2026 18:20
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