Skip to content

Fix clipped titlebar shortcut-hint tooltip and floor sidebar width to its extent#5045

Merged
azooz2003-bit merged 2 commits into
mainfrom
feat-titlebar-shortcut-hint-clip
May 31, 2026
Merged

Fix clipped titlebar shortcut-hint tooltip and floor sidebar width to its extent#5045
azooz2003-bit merged 2 commits into
mainfrom
feat-titlebar-shortcut-hint-clip

Conversation

@azooz2003-bit
Copy link
Copy Markdown
Contributor

@azooz2003-bit azooz2003-bit commented May 31, 2026

Two related fixes for the titlebar shortcut-hint tooltips.

1. Rightmost tooltip clipped against the accessory

The titlebar shortcut-hint pills (⌘B, ⌘N, ⌘[, ⌘], …) live in an NSTitlebarAccessoryViewController whose width AppKit allocates from preferredContentSize and clips to. Measured in window coordinates: the accessory ended at x=224 but the rightmost pill rendered to x=230, so AppKit clipped 6pt off ⌘].

Root cause: the accessory's reserved width and the actual pill layout were two independent computations. The reservation was a fixed inset past the button row, but the real layout runs through ShortcutHintHorizontalPlanner, which shifts the whole pill row right by ~20pt to keep the leftmost pill from crossing the leading edge (the pills are wider than the button pitch). The fixed inset never accounted for that shift.

Fix: derive the reserved width from the planner's actual rightmost hint edge via a shared titlebarHintLayoutRightmostExtent(), so contentSize reserves max(buttonReservation, leadingPad + rightmostHintExtent + shadowMargin). The pill-width measurement (SF Rounded, matching ShortcutHintPill) is extracted to a shared titlebarHintPillWidth() used by both the view and the reservation so they can't drift. After the fix the accessory ends at x=234 with the pill at x=230 (4pt clearance), pills unchanged under the buttons.

2. Sidebar minimum width floored to the accessory + tooltip extent

The default minimum sidebar width (216) is narrower than the rightmost tooltip's right edge (~234), so shrinking the sidebar to its minimum let the last tooltip spill past the divider into the content area.

minimumSidebarWidth now takes the max of the user setting and titlebarLeadingInset + clearance. titlebarLeadingInset is already measured at runtime (traffic-light inset + every leading accessory's width), and the accessory width now reserves the tooltip extent from fix #1, so it reads "everything in the accessory area plus the tooltip" with no new measurement.

Verified by measuring the rendered frames with the always-show-hints test path (CMUX_UI_TEST_SHORTCUT_HINTS_ALWAYS_SHOW=1): accessory right edge moved 224 → 234, rightmost pill 230, clearance 4pt. No automated test (pixel-level titlebar layout; a unit test would only re-derive the same geometry).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • More accurate measurement of titlebar shortcut-hint pills so pill size matches text.
    • Prevented rightmost shortcut-hint pills from being clipped by adjusting layout reservation and host view clipping.
    • Ensured sidebar minimum width accounts for titlebar shortcut-hint tooltips so right-side tooltips remain visible.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 31, 2026 4:43pm
cmux-staging Building Building Preview, Comment May 31, 2026 4:43pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Refactors hint pill measurement to use SF Rounded, computes the rightmost hint extent, centralizes hint layout constants, reserves content width from that extent to avoid clipping, updates view padding/wiring, and enforces a sidebar minimum width to preserve tooltip clearance.

Changes

Titlebar Shortcut Hint Rendering

Layer / File(s) Summary
Centralize hint layout constants
Sources/Update/UpdateTitlebarAccessory.swift
Adds hintBaseXShift, hintLeadingPadding, and hintShadowMargin to TitlebarControlsLayoutMetrics for consistent hint layout constants.
Shortcut hint pill width measurement
Sources/Update/UpdateTitlebarAccessory.swift
Adds titlebarHintPillWidth which measures pill text using SF Rounded at max(8, config.iconSize - 5) and returns measured width plus pill horizontal padding.
Compute rightmost hint layout extent
Sources/Update/UpdateTitlebarAccessory.swift
Introduces titlebarHintLayoutRightmostExtent to build width intervals for command-bound hint slots and resolve overlaps to find the rightmost reserved hint extent.
Reserve content width from hint extent
Sources/Update/UpdateTitlebarAccessory.swift
TitlebarControlsLayoutMetrics.contentSize now takes the max of button-row reservation and a hint reservation derived from the rightmost hint extent to prevent rightmost pill clipping.
View wiring and leading padding usage
Sources/Update/UpdateTitlebarAccessory.swift
Replaces hardcoded titlebarHintBaseXShift and leading padding literals with TitlebarControlsLayoutMetrics constants and updates the stored base shift reference.
Delegate hint width helper
Sources/Update/UpdateTitlebarAccessory.swift
titlebarHintWidth(for:config:) now delegates to titlebarHintPillWidth(for:config:) to use the rounded-font measurement uniformly.
Sidebar tooltip clearance for minimum width
Sources/ContentView.swift
Adds sidebarTooltipClearance and enforces a tooltip-derived floor (titlebarLeadingInset + sidebarTooltipClearance) in minimumSidebarWidth, returning max(userFloor, tooltipFloor).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • manaflow-ai/cmux#5013: Also modifies Sources/Update/UpdateTitlebarAccessory.swift layout sizing and spacing; related layout computations.
  • manaflow-ai/cmux#5017: Adjusts TitlebarControlsLayoutMetrics/contentSize/hint-related width calculations similar to this change.

Poem

🐰 Rounded pill snug on the bar,
Measured true, no clipping far,
Metrics aligned, padding set right,
Hints float free beyond the sight,
A tiny hop, layout in flight.

🚥 Pre-merge checks | ✅ 16 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description provides detailed context, root causes, and fixes, but lacks testing evidence (video/screenshot) and bot review requests as required by template. Add a demo video or screenshot showing the before/after state, and include the review trigger block with bot mentions per the repository template.
✅ Passed checks (16 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed Two new file-level utility functions and a private constant added, following existing patterns with no actor isolation violations, implicit MainActor usage, or Sendable issues.
Cmux Swift Blocking Runtime ✅ Passed No blocking synchronization found. The titlebar hint fix functions are pure layout computations without locks, semaphores, sleeps, or async waits.
Cmux No Hacky Sleeps ✅ Passed PR contains only Swift file changes (.swift), but the "no hacky sleeps" check explicitly excludes Swift code (scope limited to TypeScript, JavaScript, shell, non-Swift scripts).
Cmux Algorithmic Complexity ✅ Passed All code changes operate on fixed-size collections (5-item enum), with O(1) algorithms. No nested scans, batch rescans, unbounded iterations, or hot-path inefficiencies.
Cmux Swift Concurrency ✅ Passed The PR introduces only pure layout calculation functions with no DispatchQueue, Task, async, Combine, or completion-handler patterns introduced.
Cmux Swift @Concurrent ✅ Passed All changes in this PR are synchronous functions/properties with no async work, @concurrent annotations, or actor isolation issues. Check is not applicable.
Cmux Swift File And Package Boundaries ✅ Passed PR adds 91 and 15 lines to already-oversized files, below 250-line threshold. Focused bug fix extracting measurement logic with clear extraction paths; matches allowed cases.
Cmux Swift Logging ✅ Passed No logging violations found. PR changes in UpdateTitlebarAccessory.swift and ContentView.swift contain no print/debugPrint/dump/NSLog statements; pre-existing NSLog is DEBUG-guarded.
Cmux User-Facing Error Privacy ✅ Passed Changes add only technical layout functions (titlebarHintPillWidth, titlebarHintLayoutRightmostExtent) and layout constants. No user-facing error messages, alerts, or sensitive data.
Cmux Full Internationalization ✅ Passed PR is a technical refactoring for layout calculations with no new user-facing strings or localization keys; all comments are developer-only and no user-visible text changes.
Cmux Swiftui State Layout ✅ Passed PR introduces only local @State for titlebarLeadingInset CGFloat measured via NSViewRepresentable (AppKit bridge), with no new ObservableObject, @Published, or problematic render-time state mutations.
Cmux Architecture Rethink ✅ Passed Font-matching correction using SF Rounded instead of system font for accurate measurement. Clear ownership, no new timing, state, observers, or split lifecycle—meets allowed correctness-fix criteria.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR modifies view layout and sizing for existing titlebar hints and sidebar width; no new NSWindow, NSPanel, NSWindowController, or SwiftUI Window/WindowGroup classes are introduced.
Title check ✅ Passed The title accurately summarizes the main changes: fixing clipped titlebar shortcut-hint tooltips and flooring sidebar width to prevent clipping.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-titlebar-shortcut-hint-clip

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 31, 2026

Greptile Summary

This PR fixes rightmost titlebar shortcut-hint pill clipping by correcting the font used for width measurement (SF Rounded instead of the default system font) and by driving the accessory frame reservation from the ShortcutHintHorizontalPlanner's resolved right edge rather than a fixed trailing-inset estimate. A sidebar minimum-width floor based on the runtime titlebar inset is also added.

  • Font fix: titlebarHintPillWidth now measures with the SF Rounded font at max(8, iconSize - 5), matching ShortcutHintPill's actual render font; the old code used the non-rounded system font at iconSize - 4, underestimating command-symbol glyph widths.
  • Frame reservation fix: contentSize now takes max(buttonReservation, hintReservation), where hintReservation is derived from titlebarHintLayoutRightmostExtent — a free function that mirrors the planner's interval logic to produce a stable, modifier-state-independent width.
  • Sidebar floor: minimumSidebarWidth now enforces titlebarLeadingInset + 8 so the sidebar can never be resized smaller than the titlebar accessories require.

Confidence Score: 5/5

Safe to merge — the font-measurement and planner-driven frame-reservation changes are correct and tightly scoped to the titlebar accessory layout.

Both changed files make additive, well-contained layout fixes with no mutations to shared state or concurrency boundaries. The sidebar minimum-width floor is a computed property driven by a runtime measurement and degrades gracefully to the user-defined floor when the measurement is unavailable. The two comments flagged are a missing safety-net masksToBounds opt-out and a maintenance risk from duplicated interval logic — neither causes incorrect behavior today.

Sources/Update/UpdateTitlebarAccessory.swift — the interval-building duplication between titlebarHintLayoutRightmostExtent and titlebarHintIntervals is worth watching on any future spacing or offset change.

Important Files Changed

Filename Overview
Sources/Update/UpdateTitlebarAccessory.swift Adds titlebarHintPillWidth (SF Rounded font measurement) and titlebarHintLayoutRightmostExtent (planner-driven width reservation), refactors contentSize to take the max of button and hint reservations, and promotes magic literals to named constants. The interval-building logic in the new free function duplicates titlebarHintIntervals, and the hostingView.layer.masksToBounds = false safety net described in the PR is missing.
Sources/ContentView.swift Adds sidebarTooltipClearance constant and extends minimumSidebarWidth to enforce a runtime floor based on titlebarLeadingInset, preventing the sidebar from being dragged narrower than the titlebar accessories require.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[TitlebarControlsLayoutMetrics.contentSize] --> B{max}
    B --> C[buttonReservation
outerLeadingPadding + groupPadding
+ buttonRowWidth + hintTrailingInset]
    B --> D[hintReservation
hintLeadingPadding + rightmostExtent
+ hintShadowMargin]
    D --> E[titlebarHintLayoutRightmostExtent]
    E --> F[For each TitlebarShortcutHintActionSlot
guard !isUnbound AND command]
    F --> G[titlebarHintPillWidth
SF Rounded font at iconSize-5]
    F --> H[Compute rightEdge
groupPadding + buttonRightEdge
+ xOffset + safetyShift + baseXShift]
    G --> I[ShortcutHintHorizontalPlanner
.assignRightEdges]
    H --> I
    I --> J[max of assigned right edges]
    J --> D
Loading

Reviews (3): Last reviewed commit: "Floor sidebar width to the leading title..." | Re-trigger Greptile

The titlebar shortcut-hint pills (⌘B, ⌘N, ⌘[, ⌘], etc.) live in an
NSTitlebarAccessoryViewController whose width AppKit allocates from
preferredContentSize and clips to. The rightmost pill was being cut off on its
right edge.

Measured root cause (window coordinates): the accessory ended at x=224 but the
rightmost pill rendered to x=230, a 6pt overflow that AppKit clipped. The reason
the reservation fell short is that the hint reservation and the actual hint
layout were two independent computations. The reservation was a fixed inset past
the button row, but the real layout runs through ShortcutHintHorizontalPlanner,
which shifts the whole pill row right by ~20pt to keep the leftmost pill from
crossing the leading edge (the pills are wider than the button pitch). The fixed
inset never accounted for that shift.

Fix: derive the accessory's reserved width from the planner's actual rightmost
hint edge via a shared titlebarHintLayoutRightmostExtent(), so contentSize
reserves max(buttonReservation, leadingPad + rightmostHintExtent + shadowMargin).
The pill-width measurement (SF Rounded, matching ShortcutHintPill) is extracted
to a shared titlebarHintPillWidth() used by both the view and the reservation, so
the two can't drift. After the fix the accessory ends at x=234 with the pill at
x=230 (4pt clearance), and the pills keep their positions under the buttons.

No automated test: this is a pixel-level titlebar layout fix verified by
measuring the rendered frames; a unit test would only re-derive the same
geometry. Verified with the always-show-hints test path.
The default minimum sidebar width (216) is narrower than the rightmost titlebar
shortcut-hint tooltip's right edge (~234 in window coordinates), so shrinking the
sidebar to its minimum let the last tooltip spill past the divider into the
content area.

Make minimumSidebarWidth take the max of the user's setting and a tooltip-derived
floor: titlebarLeadingInset + a small clearance gap. titlebarLeadingInset is
already measured at runtime (TitlebarLeadingInsetReader) as the traffic-light
inset plus the width of every leading titlebar accessory, and the controls
accessory's width now reserves the shortcut-hint tooltip extent (from the prior
commit), so this reads "everything in the accessory area plus the tooltip" with
no new measurement. Falls back to the user floor when the inset isn't measured yet.
@azooz2003-bit azooz2003-bit changed the title Fix clipped rightmost titlebar shortcut hint Fix clipped titlebar shortcut-hint tooltip and floor sidebar width to its extent May 31, 2026
@azooz2003-bit azooz2003-bit merged commit cc7bd94 into main May 31, 2026
18 checks passed
hhsw2015 pushed a commit to hhsw2015/cmux that referenced this pull request Jun 1, 2026
- Add Send Ctrl-F to Terminal passthrough (manaflow-ai#5011, force-stop CC agents)
- Fix sidebar worktree spawn worktree-setup-as-input bug (manaflow-ai#5032)
- Add boundary-aware ranking layer for command-palette fuzzy search
- Open extension browser as pane tab + polish (manaflow-ai#5053)
- Move sidebar kind selection to titlebar menu, fix clipped tooltip
  and floor sidebar width (manaflow-ai#5045)
- Extract CmuxFoundation package — modular refactor wave 1 (manaflow-ai#5055)
- Center empty sidebar-extension state, fade host bottom edge (manaflow-ai#5057)
- Align titlebar accessory hints (manaflow-ai#5059)
- Restore sidebar minimum width (manaflow-ai#5062)

Conflicts resolved:
- cmux.xcodeproj/project.pbxproj: merge fork's CMUXSettingsCore +
  CMUXSessionDaemon package refs with upstream's new CmuxFoundation
  package reference and product dependency.
austinywang added a commit that referenced this pull request Jun 1, 2026
Branch had diverged behind main, which reworked the titlebar shortcut-hint
layout (#5045 clipping fix, #5059 hint alignment with defaultTitlebarHintX 4->0)
and shrank header chrome sizing. Resolution preserves the branch's intent
(restored release sizes 24/15/17/8, sidebar.left symbol, 3-slot sidebar chrome
button-count plumbing) while adopting main's newer hint-layout machinery:

- WindowChromeMetrics: keep restored sizes; add main's titlebarControlsLeadingPadding.
- TitlebarControlsHitRegions: keep sidebarChromeButtonCount/allTitlebarButtonCount
  (referenced widely by auto-merged code); adopt named outerLeadingPadding.
- contentSize: combine main's two-reservation clipping fix with the branch's
  buttonCount/reservesShortcutHintOverflow threading; bound
  titlebarHintLayoutRightmostExtent to the active slot count for sidebar chrome.
- Drop branch's superseded hint positioning (titlebarButtonRightEdge,
  hintRightSafetyShift) in favor of main's planner (hintInterval/titlebarHintPillWidth).
- Update regression anchors to merged behavior (defaultTitlebarHintX=0):
  classicWithShortcutHints 186->172, sidebar 118->104, roomy fitted spacing 7->14.

vendor/bonsplit working tree checked out to the merged pointer (adds isAudioMuted,
forkConversation* APIs that Workspace.swift now uses).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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