fix(composer): Access menu's allowed rules sit on the mode rows' columns, and only their × lights
Leo (2026-10-28, standing order): "I feel like you guys could be doing more audits of the app. Like there's some amount of, like, satisfying and pretty stuff that can happen that we're not quite taking full advantage of." And today: "you can also just look at things and notice things and see how we want to improve things."
Found in a polish audit of the composer's menus on the Linux gallery.
What was wrong
The composer's Access (permission mode) menu lists the chat's allowed rules under the modes ("Granted access": "Trusted cmux-tui", "Allow git grep in cmux for this session"), each with a remove ×.
- The section is a
<fieldset>, and only its top padding was set, so the browser's own fieldset padding (0.35em 0.75em) stayed. The heading started 6.25px left of the modes' text, each rule 4px left of it, and the × centered 21px inside the modes' number and check column. Three text columns and two trailing columns in one menu. - Hovering a rule lit its whole row, around a small × that is the only control on it, and the × drew its own pill inside that wash. The rulebook: "A hover or press highlight covers only the control it belongs to, never the whole row around a small control" (Leo, 2026-10-27: "why are you giving it the entire row when it's only this small little section? Just don't do that. Don't ever do that.").
What changed (composerLocation.css, plus one design-token baseline row)
- The fieldset's padding is set whole (
8px 0 0), not just its top. - The heading and each rule start on the mode rows' text column: 24px in (the shield's 16 + 8) when the modes draw their shield, flush when they don't (Claude Code's iconless look), chosen with
:has()on the menu. - A rule row is a two-column grid like the mode rows; the × (22px hit box) centers on the modes' 16px trailing column, 16px from the menu's edge, where a mode's number or the check sits (design/grid.md: every row type starts its text on
textand centers its trailing mark ontrail). - The row's hover wash is gone; the × keeps its own hover pill.
- The 24px lead is
padding-inline-start, so a right-to-left menu keeps the same columns from its right edge. - The rule row's old
2px 8px 2px 10pxpadding is gone, and its baselined design-token entry goes with it. The row keeps its 28px min-height (the pane is border-box), so its height and centering do not change.
Nothing else moves: the separator, the modes, the menu's width, colours and glass are unchanged. No behavior or default changes.
New test/access-grants-columns.test.ts (Chromium and WebKit; dark, light, and right-to-left): the heading and every rule start on the modes' text column (measured from the inline start), every × centers on the modes' trailing column, and hovering a rule or its × leaves the row unlit. Red on base (the heading is 6.25px off), green here.
Screenshots
Gallery: agent-pane.composer-pickers/access-grants, agent-pane.composer-pickers/permission-menu
Before (base gallery, Linux Chromium, dark): "Granted access" at 218px, its rules at 220px, the modes' text at 224px; the × at 461px against the modes' "2" and check at 482px; hovering a rule washes the whole row. After: all three on 224px, the × on 482px, only the × lights. The gallery advisory run's receipt carries both images, dark and light.
Verification
CMUX_BROWSER_TESTS=1 bun test test/access-grants-columns.test.ts test/access-chip-pending-warning.test.tsxat 80bf789: 17 pass, 0 fail, andcheck:design-tokenspasses (fast checks run 40956122298).- Red/green: with base's stylesheet the LTR cases fail (heading 6.25px off, run 40953539490). With the physical-left-padding stylesheet (9471dc5) the RTL cases fail (heading 24px off) and LTR passes (run 40955574369).
vp fmt --checkand the browser-test lane check pass.
Risk: low. Styles for one section of one menu. :has() is already used across the pane's stylesheets and is in the app's WebKit. #27144 (draft, on HOLD) moves this menu to a native popup in the app; the DOM menu stays as its fallback, and this changes none of the lines it touches.
🤖 Generated with Claude Code
Agent session: agent session
Summary by cubic
Fixes the composer's Access permission menu so the allowed rules align with the mode rows' columns and only their remove × lights on hover.
The "Granted access" rules were a fieldset whose default padding sat the heading and rules a few pixels off from the modes' text column, with each × misplaced against the trailing number/check column. Hovering a rule also washed the whole row around its small ×, against the rule that a hover highlight covers only the control it belongs to.
- The fieldset's padding is now set whole, and the heading and rules start on the mode rows' text column (24px when modes draw a shield, flush when not, via
:has()). - The lead is inline-start padding, so right-to-left menus keep the same columns from their right edge.
- Each rule is a two-column grid; its 22px × hit box centers on the modes' 16px trailing column.
- The row's hover wash is gone; only the × keeps its hover pill.
- The rule row's block padding drops off the design-token spacing scale.
Adds a browser test (Chromium and WebKit; dark, light, and RTL) covering the alignment and hover behavior, which fails on the base styles.