cmux NEXT menus: right-click menu rows keep native macOS metrics

Merged
TE
13d ago
+261-13

Leo-ask: ask-6cdd1614cb

Leo, on the chat's right-click menu (Copy, Quote in Reply, Ask About This, Search the Web):

RIGHT CLICK THIS IS OFF... FUNDAMENTALLY THERE'S SO MUCH BULLSHIT PADDING AND WHATNOT LIKE ALL OVER THE FUCKIGN PLACE ... GLASS BUT NOT BULLSHIT

What changed

Measured on Leo's screenshot (a 2x capture): rows 22pt, title text 13pt, top inset 5pt, trailing 12pt, all native; but the icon started 23pt and the title 44pt in from the menu's edge, where a native menu with icons starts its icon at 15pt and its title at about 35pt.

That menu is native: AgentPaneContextMenu themes WebKit's menu with NSMenu.themeRows(in:), so every row is a ThemedMenuRowView. The glass panel, its corners and its separators are AppKit's own; the bloat was in the row:

  • Every row reserved an empty checkmark column, so each icon started 22pt in from the menu's edge. A native menu without checkmarks starts its content at 15pt, where its separators start. Rows now start there; a menu where some row it shows has a checkmark or dash keeps the 22pt state column, as a native menu does. A hidden checked row (the device menu's search hides its browse rows) leaves no column. Clearing the device search while the menu is open re-measures it, so the column comes back to every row (BrowserDeviceSearch.apply themes the menu on an empty query too).
  • The icon box is 14pt (was 16pt). Icons are fitted with base's fitted(_:in:): scaled down, never up, shape kept.
  • Rows stay 22pt in the native 13pt menu font. The highlight stays 5pt in from the edge with a 4pt radius.
  • A menu's state and icon columns are measured once, in one pass over the menu, each time it is themed (themeRows, themeAddedRows, a submenu's menuNeedsUpdate) or opens, and handed to its rows (ThemedMenuColumns). A row's draw and width read only that value and its own item, so a long menu (every device) does no per-row menu scan on redraw (Codex review of d630a18c). Before this, hasIconColumn already scanned the whole menu on every row draw; it now reads the same cached value.

This applies to every themed menu (sidebar, tabs, terminal, browser page, bookmarks, downloads and the agent chat), since they share the row view.

ThemedMenuMetricsTests pins the metrics: 22pt rows, the native menu font, 15pt leading with no state column (22pt with one), a hidden checked row leaves no column (rows themed before the search drop it too), a 14pt icon box that keeps each symbol's shape and never scales up, the 5pt highlight inset with a radius of 6pt or less, AppKit's own separators, and the columns are measured once per theming and never while rows draw (200 rows themed, 20 drawn, then a checked row added and themed moves every row into the state column).

No webview changes: the menu Leo showed is not a webview menu, so #23066 (popup CSS) does not touch it.

Verification

  • Fleet compile-check (cmux-ci compile-check --ref 78fd007c98d78b82b11656eea6c525cf06270c96 --app): passed (job 173166b2f49c61ec25643d9b, 55 s).
  • Fleet focused tests at 78fd007c (ThemedMenuMetricsTests, ThemedMenuIconTests, ThemedMenuTests, AgentPaneMenuLookTests, BrowserToolbarMenusThemeTests, BrowserDeviceMenuTests, BrowserDownloadsMenuThemeTests, SidebarMenuLookTests, PaneMoreOverflowButtonTests): all 9 suites passed (step 8da56e37586a5cdcdfe9a11a), including the new columnsAreMeasuredOncePerTheming and clearingTheDeviceSearchBringsTheStateColumnBack.

Observed / Not run

  • Not run yet: the capture of the menu on a capture mini.

Changelog

  • Changed: right-click menus use native macOS spacing: icons start at the menu's edge inset and draw at the native size.

Agent session: cosmic-gray

🤖 Generated with Claude Code