cmux NEXT Settings: menus hug and align with their trigger, Check Every in hours

Merged
TE
6d ago
+412-6

Leo: "look for wastage"

Settings > Updates with the Update Channel menu open. The menu is the shared ui/Select (webviews/src/ui/Select.tsx), so the fix is made once in the component and covers every select in Settings. Spec: leo-workspace design/settings.md (teamleaderleo/leo-workspace#1746), which this PR maps in .github/design-surfaces.json as the settings surface. Row lines follow design/grid.md 5.3 and schemas/menu-metrics.

The waste, before and after

Measured in Chromium and WebKit by webviews/test/settings-select-menu-browser.test.ts (gallery pages.settings / updates, 900x640, 2x). The menu opens at x=611 under a 200 px trigger.

ItemBefore (base 0dd8fd0)After (d311c38)
1. Checkmark guttercheck centered at 18 px, every label at 30 pxcheck on the state column at 10 px, labels at 22 px. A select's rows never carry an icon, so no icon column is reserved
2. Row height28 px plus 2 px padding above and belowrows on --ds-control-row (28 px), no extra padding; popup inset 5 px (menu metrics)
3. Menu vs triggerleft edge 611 = trigger 611, but 160 px wide under a 200 px triggerleft 611 = trigger 611, width 200 = trigger 200 (min-width: max(var(--anchor-width), 160px)); grows only for longer rows
4. Check Everyslider + "3600 s"slider + "1 hr". The stored value is still seconds: the page converts only where it shows and parses the number (format.ts shownUnit), so nothing migrates. Install Within now reads "10 min"; Quiet For stays in seconds
5a. Glass bleed-throughtint 60%, blur(20px) saturate(1.4); "3600" and the slider read throughmenu glass tokens: tint 78%, blur(32px) saturate(1.6). Still translucent (under the surface roles' near-opaque 0.9); Reduce Transparency still makes it solid
5b. Clipped "Updates" headernot reproduced in the gallery: the title's top is at 38 px and the scroller's clip line at 6 pxunchanged. The test asserts it stays unclipped

Not touched: every control and option, every default, the open (still one frame, no fade-in).

Stills (2x, synthetic gallery data)

BeforeAfter
Light, WebKit
Dark, WebKit
Light, Chromium
Dark, Chromium

Viewed after image: yes. The menu now starts on the trigger's left edge and ends on its right edge, the check and labels sit close to the left edge, and the rows are tighter. Check Every reads "1 hr". In Chromium the toggle and slider under the menu are frosted. The Linux headless WebKit used for these stills does not draw backdrop-filter (base and head alike), so there only the stronger tint shows and the controls under the menu are faint but visible. The computed styles are the same in both engines (alpha 0.78, blur 32px), and macOS WebKit in the app draws the blur.

Visual verdict (ux-owner, Claude Opus 5.5): SHIP at d311c38bc6257c31f3334eece35b150a60534003. The menu hugs the trigger edge to edge, the gutter is tight, the frost hides the controls behind it while staying translucent, Check Every reads "1 hr", and everything fits on screen with nothing repeated.

The same audit across Settings

The sweep in the same test opens every enabled select on every Settings page (67 menus) and holds each one to the same rule: left edge on the trigger, never narrower, rows on the token, text at 22. Result at d311c38: 0 findings. One menu, Appearance > Background (149 painting titles, up to 71 characters), is wider than the space to the right of its trigger, so Base UI slides it left to stay in the window, as an AppKit menu does. The sweep lists that case instead of failing it. The font and theme pickers are Popover + Combobox, not selects, and row context menus use ContextMenu; neither is changed here. Their row grid is covered by #27616 and their glass role by #27838.

Tests

  • Red first: a009b79 (the test alone) failed at base in all 4 engine x appearance cases (run 41129061253: popup 160 px under a 200 px trigger, check at 18, text at 30).
  • Green: bun test test/settings-select-menu-browser.test.ts src/pages/settings/ test/checkmark-alignment.test.ts test/glass-never-opaque.test.ts test/settings-scroll.test.ts test/popover-instant-open.test.ts at d311c38 via cmux-ci test: 402 pass, 0 fail across 69 files (run 41130984910).
  • scripts/web-lint.sh passed, check-glass-never-opaque passed (no opaque fills), check-menu-metrics.py passed, prepush-gate.py passed.

Observed / Not run

  • Observed: the Chromium and WebKit gallery stills above, their geometry, and the test runs listed.
  • Not run: a native capture on a Mac (Settings is a webview, so the gallery is the capture). Not run: the full webview suite beyond the files listed.

Changelog

Fixed: Settings menus line up with the button that opens them, have tighter rows and a frosted background, and Check Every reads in hours.

Agent session: agent session

šŸ¤– Generated with Claude Code