CmuxNext: reasoning menu drawn as a native menu
Problem
The reasoning menu didn't look like a native menu:
- Ultracode's note ("xhigh effort plus multi-agent workflow orchestration") wrapped to two grey lines, so that row was about twice as tall as the others.
- The checkmark sat at the trailing edge, so the menu had no fixed leading gutter like NSMenu.
- Section headers and the separator didn't follow a consistent inset or vertical rhythm.
- In the access menu, the 1โ4 key numbers were set larger than the row titles.
Change
- Ultracode now has a short note on the same line as its name, in secondary text: "Extra High + multi-agent". The note is rewritten in all 21 locales. If a menu ever clips the note, its full text shows in a tooltip.
- Check gutter. Every row (Reasoning and Fast Mode / Service Tier) is a two-column grid: a 16 px leading check gutter, then the label. Unchecked rows keep the empty gutter, so all labels start at the same x. The access menu already used this gutter and now shares the same check styling.
- Row height. Every row is one height (
--ui-row-height, 28 px). - Section headers align with the label column and use a 24 px caption in secondary semibold.
- Separator. A 1 px hairline, inset to the row edges, with 5 px above and below.
- Access menu. The 1โ4 numbers are now secondary key-equivalent text (muted, detail size, tabular figures).
- The menu's max width grows from 240 px to 280 px (still capped at
100vw - 24px), so the note fits beside "Ultracode".
Unchanged: which options exist, the default selection, hotkeys, and the footer row (owned by op-next-composer-footer-cx).
The reasoning-claude gallery variant now gives Opus the Extra High level, so the menu shows Ultracode as the variant's note already promised. Before this, the fixture's Opus lacked xhigh, so Ultracode was filtered out.
Borrowed from AI Elements
- Restraint: menu items stay normal weight; only the section headers are semibold, and the note and key numbers use the muted secondary color rather than a new accent.
- Spacing: a tight 4 px grid, with one row height and a fixed 16 px icon-size check gutter.
- One deliberate departure: AI Elements puts the check trailing (
right-2) and drops descriptions; we keep a leading gutter like NSMenu and a one-line note for Ultracode.
Stills
Gallery agent-pane.composer#reasoning-claude, Catppuccin Latte and Mocha, at 760, 400 and 300 px panes.
Reasoning menu
| Width | Light before | Light after | Dark before | Dark after |
|---|---|---|---|---|
| 760 | ![]() | ![]() | ![]() | ![]() |
| 400 | ![]() | ![]() | ![]() | ![]() |
| 300 | ![]() | ![]() | ![]() | ![]() |
Access menu (shared gutter, secondary key numbers)
| Width | Light before | Light after | Dark before | Dark after |
|---|---|---|---|---|
| 760 | ![]() | ![]() | ![]() | ![]() |
| 400 | ![]() | ![]() | ![]() | ![]() |
| 300 | ![]() | ![]() | ![]() | ![]() |
Tests
Two commits:
- Adds
EffortPicker.test.tsx(red on the base). - Adds the fix.
The tests cover:
- Every radio row, checked or not, is exactly [check gutter, text].
- The checked rows are Medium and On.
- Ultracode's note sits inside the row's text line, with its tooltip.
- In every locale table, the note is one line of at most 32 graphemes.
Commands run in webviews/:
bun test src/agent-session/acpmux/EffortPicker.test.tsx(3 pass)bun test src/agent-session/acpmux src/ui(34 pass)- The stylesheet suites: popup-surface, popup-one-hairline, composer-menu-width, check-type-scale, subtle-elevation, text-field-focus, agent-pane-mode-keys (47 pass)
bun run typecheckandbun run check: clean
The change is web-only, and no Swift was touched.
Localization audit: effort.ultracodeDetail is updated in all 21 locales (ar, bs, da, de, en, es, fr, it, ja, km, ko, nb, pl, pt-BR, ru, th, tr, uk, vi, zh-Hans, zh-Hant), and generated/strings.json was regenerated. Non-English entries stay needs_review, and ja moves to needs_review because its text changed. No other new strings.
๐ค Generated with Claude Code























