cmux-next: composer controls stay grouped and steady during a turn (hq#1957 item 15)

Closed
TE
22d ago
+1200-241

Fixes the agent composer's controls row and stops the composer from shifting during a turn (hq#1957 item 15; Leo: "this is super weird", "so much layout shift while a subagent runs").

Controls row

  • Before: the permission chip was a fixed 180px wide behind a flex spacer, so "Auto" floated in the middle of the row and left a big gap.
  • Now: plus, model, ring, effort and permission sit together on the left; mic and Send/Stop sit on the right. Free space appears only between the two groups.
  • In a narrow pane, labels give way in order: the permission label goes first (lock icon only), then effort, then model.
  • The footer row (folder, host, branch) can grow but never shrinks. It keeps 12px side and 10px bottom insets, so it is no longer clipped.

Layout shift during a turn

  • The context ring used to appear at turn start. It now holds its slot once a session exists, so a prewarmed new chat shows an inactive ring.
  • Steer (shown when you type during a turn) used to push the mic left. It now comes in to the left of the mic.
  • The queue, permission asks and PR dock already grow upward over the transcript. Send/Stop is the same 32px circle. A mode change moves no other control.
  • Exception: in a narrow (~420px) row, the left cluster may shift when Steer appears, because there is no spare room to reserve.
  • The labels/icons switch has hysteresis: it leaves icon mode only with 4px of clear room, so it cannot flip every frame.

Compact row (Leo: "tonka toys")

  • The left group is "+ · model · effort · access", with even 8px gaps between 28px controls. Hover is a light wash that sits tight to each control.
  • The context ring is no longer in the row. Context usage now shows in the model chip's tooltip ("Opus 5.5 · 42% of context used"). The context details popover and its Compact button are gone from the pane; /compact still works.
  • The "Trusted this chat's…" chip has no slot in the row (op-next-composer-footer-cx is removing it), so the row shows one lock at most.
  • Stop is the same 28px grey circle as Send, with a 7px square. It replaces the large white disc.

Edges (border hunt, op-next-theme)

  • #20303 added a glass shadow and a text-color rim to the composer card. Both are gone. The card keeps one thin Apple-like rim, the 0.5px --acpmux-composer-edge hairline, which appearance.borders = none clears (Leo: a thin Liquid Glass rim is good, don't strip it to zero).
  • Permission cards keep one 0.5px hairline in the same edge color, with no shadow. A test guards that the hairline stays.
  • The permission panel's gallery entry now loads the pane's stylesheets inside .acpmux-shell. Before this, its edge checks measured an unstyled card and passed without testing anything.
  • The New Tab box loses its drop shadow, both at rest and when focused.
  • Keyboard focus still shifts the card's edge toward the accent color. That is a focus state, not a border, so it stays under borders = none.

Verification

  • Edges: CMUX_BROWSER_TESTS=1 bun test test/composer-edges.test.ts was red at 4580bd4130c (0/5) and at acab5b5e9df (New Tab), and is green 6/6 at a585a87afeb. With the real permission card measured (600aa9e50b0), the CSS from before the fix fails 6 of 7 checks and the fix passes 7/7. Of the related composer, New Tab and permission suites, 132 pass and 1 fails: new-tab-chat-title-width, which fails the same way on the base.
  • Compact row: CMUX_BROWSER_TESTS=1 bun test test/composer-row-layout.test.ts test/composer-turn-cycle.test.ts was red at d5fa4a0de6a (3 pass, 30 fail) and green at 1bebce0ad46. bun test test/composer-*.test.ts passes 53/53. Captures are on big-red at /tmp/cg-lane-adopt-dogfood/compact-{before,after}-*.png.
  • CMUX_BROWSER_TESTS=1 bun test test/composer-row-layout.test.ts: red 0/12 on eddade242f3, green 12/12.
  • CMUX_BROWSER_TESTS=1 bun test test/composer-turn-cycle.test.ts: red 0/6 on 397913287ba, green 6/6. It checks that the input and every control stay within 0.5px through idle → running → 1 subagent → 3 subagents → asking → queued → finished.
  • bun test test/composer-row-fit.test.ts (switch hysteresis): red 1/3, green 3/3.
  • bun run check passes; a review subagent found no blockers, and its flip-flop finding is fixed above.
  • Unverified: Chromium only, not WebKit or the native app. I could not reproduce Leo's exact footer clipping outside the gallery.
  • Screenshots (before/after at 420, 720 and 1100px, plus the turn cycle) are on big-red at /tmp/cg-lane-adopt-dogfood/composer-*.png.

Changelog

Fixed: the agent composer's controls form one compact row (stop matches send, no spinner) and no longer shift while a turn or subagent runs.

🤖 Generated with Claude Code