cmux NEXT composer: one pill primitive for every control, with a guard

Closed
TE
12d ago
+581-256

Leo-ask: ask-d4eed794c9

this basically did we have a genearlized solulu to the weird pills? that you added to the bottom?

Each composer control used to size itself: the mode, model and effort chips were 28 px capsules with their own padding (0 6px 0 8px, 0 8px 0 6px, 4px, set in three sheets); the mic, Send and the bolt were 28 px circles; the context ring was 24 px; New Tab's mic was 24 px; the dictation finish key was its own circle; and the + button sat 10 px from the box's left edge, 6 px from its top and 8 px from its bottom. Lawrence's review notes called these out ("weird padding" on the mode and model pills, "left/top/bottom padding" on +).

Now every composer control is one primitive, .acpmux-pill, with .acpmux-pill-icon for a square. Only the --acpmux-pill-* tokens in composerLocation.css size it:

tokenvaluewhat
--acpmux-pill-height24pxa label pill's height
--acpmux-pill-pad6pxa label pill's sides
--acpmux-pill-icon28pxan icon pill's square
--acpmux-pill-gap4pxicon to label
--acpmux-pill-radius999pxone corner for all of them: the Claude app's soft pill that #22107 and composer-chip-plain-rest hold, so a label pill is a capsule and an icon pill a circle
--acpmux-box-inset8pxthe controls from the box's top, bottom and right; the prompt's line is centred in the same height, so a one-line box is 44 px (Claude desktop's, measured 10-20)
--acpmux-box-lead10px+ from the box's left, which puts its glyph 16 px in (Claude desktop's, measured)

The pill shows its background only on hover of that button, or while its menu is open. It has no rest fill, no box highlight and no press tone. Send keeps its glyph colour on hover, has no disc and gets no new dot. Menu contents, the harness picker, the queue strip and the New Tab dots are unchanged. A narrower row changes tokens (--acpmux-pill-pad: 4px at 260 px), never a control.

Inventory (base → head, chat pane at 720 px, dark)

pillbasehead
box (one line)42 px44 px
+ attach28Ɨ28, r 6 (a square), left 10 / top 6 / bottom 828 circle, left 10 / top 8 / bottom 8
mode ("Auto")28 h, pad 4 (foot) or 0 8 0 6 (other sheet), r 99924 h, pad 6, r 999
model ("Opus 5.5 Medium")28 h, pad 4 (foot) or 0 6 0 8, r 99924 h, pad 6, r 999
effort / Options28 h, pad 0 6 0 8, r 999 / r 624 h, pad 6, r 999
Plan28 h, pad 0 8 0 6 or 6, r 6 or 724 h, pad 6, r 999
mic28 circle, top 6 / bottom 8 (24 in New Tab)28 circle, top 8 / bottom 8 (28 in New Tab)
Send / Stop / ↵28 circle28 circle
Codex bolt28 circle28 circle
dictation finish28 circle (24 in New Tab)28 circle
context ring24 circle in the foot, 28 elsewhere28 circle
hover11% wash, from 4 different rules11% wash, one rule; none at rest

Guard

The pill guard (scripts/cmux-next/check-composer-pills.py, its test and the check:composer-pills hook in bun run check) moves to a follow-up PR, from branch composer-look-pill-guard, so this one stays under the ~800-line limit. It fails a composer stylesheet rule that sizes a control itself and a control's JSX without acpmux-pill; this branch's head passes it (48 stylesheets, 240 views).

Gallery

agent-pane.composer-row gains pills-tight (22 px labels, 4 px sides, inset 6: a 40 px box), pills-even (24/6, inset 8: a 44 px box, the default) and pills-roomy (28/8, inset 10: a 48 px box), each with the model button hovered. I picked even: the label sits as far from its pill's sides as from its top and bottom, + and the mic sit 8 px off the box's top and bottom (base had 6 and 8), and the box is Claude desktop's 44 px. Tight crowds the label against its hover wash. Roomy brings back the "incessant left-right padding" Leo flagged on 10-21.

Tests

On huge-blue (Linux, Chromium, CMUX_BROWSER_TESTS=1 for the browser lane), with scripts/ci/run-webviews-tests.sh:

  • The 56 webviews test files that read these classes pass at 6393deef, except test/newtab-quiet-focus.test.ts, which fails the same 7 of 22 tests at base 258708d7 (the rim and surface checks; this PR doesn't touch them). Browser-lane files that pass include composer-row-rhythm, composer-chip-plain-rest, composer-top-strip-variants, composer-plain-glyphs, composer-footer-plain, composer-claude-split, composer-row-layout, composer-fit-steps, agent-pane-no-capsules and focus-visuals.
  • bunx vp check (format, lint, types): the only errors come from files this sparse checkout lacks (generated strings.json), none in the changed files.
  • cmux-ci compile-check --ref 6393deef49a8680460ca52e2b72738dbec3d463c --app: passed, job 0fa539009c51cdf347133d8b.

No capture: webview-only change; the gallery variants above and the agent-pane.composer-row and agent-pane.new-tab entries show it.

Agent session: cosmic-gray

šŸ¤– Generated with Claude Code