Menu bar: recording indicator, adaptive appearance, quick menu, timer, dead-code cleanup#1351
Menu bar: recording indicator, adaptive appearance, quick menu, timer, dead-code cleanup#1351r3dbars wants to merge 4 commits into
Conversation
The status item glyph never changed, so a recording app gave no menu-bar signal that capture was active. The status button now shows a red record.circle while a meeting records and a red mic.fill while dictating, with matching tooltip and accessibility label, through a single presentation writer so the indicator and the update badge can't fight over button state. The popover now answers the same question: the header shows a red Recording status while a meeting records, and the meeting row's trailing slot shows the live elapsed mm:ss timer (via MeetingDurationFormatter) instead of the start shortcut. Duration ticks arrive at 5 Hz, so the refresh subscription collapses them to whole seconds and skips entirely while the popover is closed. Also removes the orphaned menubar UI kept alive only by contract tests: MenuBarSettingsView, MenuBarShortcutsView, MenuBarModelStatusView, MenuIconButton, and MenuOutlineButton were no longer in the live popover hierarchy. Their contract-test assertions, now-unused MenuTokens, and stale doc/QA-matrix pointers are cleaned up in the same change. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017MdpDAQ4jVvGbiFa2VA91n
… status policy The popover forced darkAqua at three levels (popover, panel controller, content view) with dark-only white-alpha tokens. MenuTokens colors are now dynamic — dark variants keep the original look, light variants mirror them — and the forced appearances are gone so the popover follows the system setting. Colors written into CALayers are appearance snapshots, so views re-resolve them through NSView.menuResolvedCGColor and re-apply from viewDidChangeEffectiveAppearance. Also drops the now-dead SwiftUI wrappers and onboarding window tokens. Right-clicking (or control-clicking) the status item now opens a lean quick menu — start/stop dictation, start/stop meeting recording, open Home, quit — reusing the same session/overlay entry points as the popover and command menus. Plain left-click keeps the popover; the menu is attached only for the duration of the click. The header status line (Recording > Ready > warmup subtitle precedence) moves into a Foundation-pure MenuBarHeaderStatusPresentation policy with fast-test coverage, and the utility updates row now uses the state-specific symbol the presentation helper already computed instead of a hardcoded icon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017MdpDAQ4jVvGbiFa2VA91n
…er motion
Subtraction first: steady states stop talking. Ready-state subtitles
("Paste spoken text anywhere", "Capture mic and system audio",
"Recording now") are gone — subtitles now only carry setup/failure
state, so the everyday popover reads as clean single-line actions. The
Paste Last Dictation row hides until a saved dictation exists instead of
advertising its own empty state (the launch-smoke override still forces
it visible for automation). The update callout is reserved for
restart-to-install; available-but-not-downloaded stays in the quiet
utility row. Quit drops its warning tone, feedback gets title case, and
the header/home dividers are gone — one divider remains above the
utility section.
Color is now reserved for state: primary rows are monochrome and the
meeting row turns red only while recording. This pass also fixes a real
bug from the recording-header change: intrinsicHeight returned 0 for
ready+quiet regardless of recording, so the red Recording header never
actually showed. MenuBarHeaderLayoutPolicy now takes isRecording and
gives the recording state a compact visible row, with new fast-test
coverage.
Material and motion: the content view stops painting its own opaque
surface so NSPopover's native material provides the background, corner
chrome, and Reduce Transparency behavior. Row hover states ease in and
out over 120ms through AccessibilityDisplayPolicy.motionDuration so
Reduce Motion collapses the fade; presses stay instant. The status-item
update badge loses its dark border and shrinks to a 7px dot.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017MdpDAQ4jVvGbiFa2VA91n
Code-derived mockup of the popover states on this branch (light idle, dark idle with hover, dark recording, right-click quick menu), rendered from the exact MenuTokens values, row heights, and copy. Not a live macOS capture — this session had no macOS host — so fonts, material blur, and icons are approximations; geometry, colors, copy, and states match the code. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017MdpDAQ4jVvGbiFa2VA91n
|
Maestro hold review: HOLD at head 973c5ff. This is the only non-draft PR in the batch and CI is green, but it changes the primary menu-bar surface: status glyph, recording indicator, right-click/control-click quick menu, popover appearance, timer, hidden paste row, update affordance, and deletes old menu components. The attached visual is code-derived, not a live Mac capture. Smallest clear path: run a local Mac visual/UI pass in light and dark mode, verify right-click/control-click menu actions, live dictation/meeting recording state, update-ready badge coexistence, and paste-row visibility; then recheck exact head and merge if unchanged. |
|
Maestro local proof follow-up: HOLD at head What passed locally on this Mac:
Still held because the required mapped command The built/signed app can launch directly and the UI behavior looks good, but the repo-owned gate does not pass, so I did not merge. Local evidence is under Smallest next action: fix or account for the LaunchServices |
Why
The menu bar is the app's primary surface, but it wasn't behaving like one: the status item glyph was completely static (no signal that recording was active), the popover header said "Ready" during a meeting with no elapsed time anywhere, the popover forced dark appearance regardless of the system setting, everyday states carried permanent explainer copy, and ~1,150 lines of
Sources/UI/MenuBar/were orphaned code kept alive only by contract tests that read the files.Product Impact
dictation/meetingsactivationPreview
Code-derived mockup (
.agent-review/visuals/menu-bar-premium-redesign.{html,png}) rendered from the exactMenuTokensvalues, row heights, and copy on this branch — not a live macOS capture (this session had no macOS host). Fonts, material blur, and icons are approximations; geometry, colors, copy, and states match the code.What changed
Commit 1 — recording indicator, popover timer, dead-code removal
record.circlewhile a meeting records and a redmic.fillwhile dictating, with matching tooltip and accessibility label, through a single presentation writer so the indicator and the Sparkle badge can't fight.mm:sstimer while recording (5 Hz core ticks collapsed to whole seconds; no refreshes while the popover is closed).MenuTokens, updated docs and the QA matrix pointer.Commit 2 — adaptive appearance, quick menu, header policy, icon passthrough
darkAquaremoved,MenuTokenscolors made dynamic, CALayer-bound colors re-resolved viaNSView.menuResolvedCGColor(_:)onviewDidChangeEffectiveAppearance().MenuBarHeaderStatusPresentationwith a fast test; utility updates row uses the computed state symbol.Commit 3 — premium polish: quieter popover, native material, motion
Tone.recording) only while recording. Theaccenttone is gone.MenuBarHeaderLayoutPolicy.intrinsicHeightreturned 0 for ready+quiet regardless of recording. The policy now takesisRecordingand gives it a compact visible row, with new fast-test cases.AccessibilityDisplayPolicy.motionDuration(Reduce Motion collapses it); presses stay instant. Status-item update badge loses its dark border, shrinks to a 7px dot.Commit 4 — visual evidence under
.agent-review/visuals/.Deliberately not done (need visual iteration on a Mac): a custom-drawn status glyph to replace
mic.and.signal.meter, and replacing NSPopover with a borderless panel. Both are design-taste calls not worth making blind from a Linux container.How I checked it
scripts/dev/agent-preflight.sh.agents/test-matrix.yml— via CI:build-and-test(build + fast tests + launch UI smoke) green through commit 3, including the updated smoke expectations (hidden idle header, gated paste row, "Submit Feedback")bash build.sh --no-open— via CI (no macOS toolchain in this session)bash run-tests.sh— via CI, including the newMenuBarHeaderStatusPresentationand recording-header layout-policy casesbash run-integration-smoke.sh— meeting sources untouchedswift test— core seam untouchedCaveat: all build/test verification ran through CI rather than a local Mac. The popover still deserves a human visual pass in both appearances before merging — the native-material change is the one most worth eyeballing against the preview above.
Risk Review
menu_bar_action_clickedevent.agent-review/visuals/evidence —menu-bar-premium-redesign.{html,png}(code-derived mockup; noted as such)Notes
Launch UI smoke: header assertion unaffected (status strings stay populated even when the header view is hidden); paste-row visibility satisfied via the smoke's existing visibility override; "Submit Feedback" expectation updated in
scripts/entrypoints/build.shin the same commit. Focus-order contracts unchanged.OverlayTokens(recording HUD) deliberately stays dark.Agent handoff
COORD_DONE: GREEN | https://github.com/r3dbars/transcripted/pull/1351 | recording indicator + adaptive appearance + quick menu + timer + quieter popover + native material + hover motion + dead-code removal + visual evidence | none | custom status glyph & borderless panel deferred (need visual iteration) | CI green (build, fast tests, launch UI smoke) + agent-preflight | human visual pass on a Mac (light/dark), then merge🤖 Generated with Claude Code
https://claude.ai/code/session_017MdpDAQ4jVvGbiFa2VA91n