fix(picker): native menu density for the compact model menu
Summary
Leo (2026-10-28), on the compact model menu: "AND I THINK IT'S ALL SO STUPIDLY SPACED AND STYLED IT'S FUCKING TONKA TOYS". His screenshots showed a big "Type to search models" field, harness rows with large icons, Effort / Provider / Fast mode rows in large type with a big switch, and an Effort submenu with tall rows and a far-right check.
The menu now uses a native macOS menu's density, matching Claude desktop's and the Codex app's pickers, with our colours and glass unchanged:
- Rows, rail tabs and the search field are 28px tall (36px before). Submenu rows (Effort, Provider, More models, Retry's More models) are 24px.
- Text uses the 13px chrome size (
--text-body), not the transcript's content size, which follows the reading-size setting and made the menu grow with it. - Tighter insets: 4px menu padding, 10px corners, 5px row corners, and rail tabs at row height with no extra gap.
- Fast mode's switch is 28Ć16 with a 12px thumb, and it now sits inside its row. Before this change the row's check grid pushed it across the row's right edge.
- The check and number-key column is 16px, with the check centred on the label's line.
- Menus still open on the click with no fade-in (the browser test checks this).
This takes back part of #26071 (merged 2026-10-28), which set this menu's text to the content size: Takes back #26071: Leo asked for native menu density in the quote above, and content-size type is what made the rows grow.
Gallery: agent-pane.model-menu-density shows four versions, each with the list open and the Effort submenu open: native (ships), tight (24/22px), roomy (32/28px) and before. I picked native because it matches the native menu metrics Leo compared against. tight clips the 13px type's line box, and roomy still reads large next to Claude desktop.
Related: #27303 (the same menu's search; independent, no overlapping lines), #27232 (checkmark centring across picker surfaces; this PR only sets the quick menu's own check column), #27140 (native popup migration of these menus).
Testing
webviews/test/model-menu-density.browser.test.ts(new, real Chromium): rows, rail tabs and the search field are 28px in 13px type; marks are at most 16px; the switch is at most 16px tall, 28px wide and inside its row; Effort submenu rows are 24px with the check within 1px of the label's centre line; the menu opens at opacity 1 with no running animation. It is committed before the fix. On the base, three of its four tests fail (rows 36px in content-size type, the switch, the submenu rows); the no-fade-in test passes on both.- Updated
test/quick-model-menu-layout.test.ts(rows are 28px, not at least 36px) andtest/retry-model-menu.test.ts(rows use the chrome text size; the row-height token is read through a probe now that it is acalc()). - Ran on the fleet (
cmux-ci test, 32-vCPU Linux):bun run checkpasses, including the design-token ratchet, whose baseline shrinks by two entries. The density, retry-menu, layout, bounded-height, compact-menu, QuickModelMenu, submenu-up, New Tab clip, retry, default-effort and effort-slider suites pass. Two failures are not from this change.the optional reasoning slider replaces Effort's levels only when enabledfails the same way on base.effort-picker-slider.test.tsx(a JSDOM test ofEffortPicker, which loads no CSS and renders no menu this PR touches) failed one case in 2 of 4 head runs alongside other suites, a different case each time; it passed 17/17 alone at the head and 3 of 3 times at the base.agent-pane-no-capsulesneeds a built agent pane and fails at the base too on the fast-check box.
Observed / Not run
- Observed: the fleet runs above, and the before/after stills below from one harness at the base and at this head.
- Not run: a native app build. This change is webview CSS only.
Changelog
Changed: The model menu uses native menu sizing: 28px rows, 24px submenu rows, 13px text and a smaller Fast mode switch
Proof
Same harness, real Chromium, dark theme, at the base and at this head. The harness doesn't load the glass backdrop, so the submenu shows without its fill on both sides.
| Before | After |
|---|---|
![]() | ![]() |
![]() | ![]() |
š¤ Generated with Claude Code
Agent session: agent session



