Skip to content

cmux NEXT menus and pickers: checkmarks, icons, text and shortcuts on one menu grid (draft: red measurement first) - #27616

Open
teamleaderleo wants to merge 16 commits into
feat-cmux-nextfrom
lane/grid-menu-lines
Open

teamleaderleo wants to merge 16 commits into
feat-cmux-nextfrom
lane/grid-menu-lines

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

HOLD: landing waits until base is restored (webview reds from #27559, #27570 and #27580); the grid coordinator lifts this line.

Leo, 2026-10-29: "we need to have better fing grids. We need to have the fing stuff aligned on f***ing grids and lines" (and, the night before, misaligned checkmarks).

Puts every webview menu outside the Claude Code pickers on AppKit's menu metrics (schemas/menu-metrics, --cmux-menu-*; spec: leo-workspace design/grid.md 5.3): the highlight 5 from the popup edge, radius 5, 28 rows, the checkmark centred on the state column at 10 in every row of a menu that has one, icons on one column, and the text on one column. One shared rule in popupSurface.css replaces each menu's own row padding.

An icon column is reserved only when a row in the menu carries an icon: the text starts at 15 with no state column, at 22 right after the check (the select keeps #28530's 22, design/settings.md), and at 35 or 42 when there are icons.

Kept as they are, because a newer settled design puts the chosen row's check in its number's place at the trailing edge: the model picker and its side menus (#29791, design/model-picker.md), its effort menu, and the mode menu (Claude Code's look, Leo 2026-10-19; composer-claude-split.test.ts, access-grants-columns.test.ts). Whether grid.md 5.3's leading state column should also cover them is a follow-up for the picker owner.

Measured (Chromium, gallery, light; px from the popup's leading edge)

Menu highlight inset before → after check x before → after text x before → after row h before → after
composer + (palette) 0 → 5 none 32 → 35 46 → 46 (two-line rows)
chat ⋯ menu 4 → 5 none 35 → 35 28 → 28
ui.menu (shared) 4 → 5 18 → 10 12 / 30 → 22 28 → 28
ui.select 5 → 5 10 → 10 22 → 22 28 → 28
context menu 4 → 5 none 12 → 15 28 → 28
combobox 4 → 5 none 12 → 15 24 → 28
project chooser 4 → 5 284 (trailing) → 10 32 → 42 28 / 46 → 28 / 44

Right-to-left, every column above measures the same from the menu's leading edge, headings included.

Before / after (gallery, Linux Chromium, 2x, light and dark)

Menu Before After
ui.menu (light) before after
ui.menu (dark) before after
ui.select (light) before after
ui.select (dark) before after
context menu (light) before after
context menu (dark) before after
combobox (light) before after
combobox (dark) before after
project chooser (light) before after
project chooser (dark) before after
chat ⋯ menu (light) before after
chat ⋯ menu (dark) before after
composer + (light) before after
composer + (dark) before after

I opened every after image: the checks sit on one state column, icons and titles on one column each, headings on the titles' column, and the project chooser's hairline back on the separator inset. The composer + menu's filled search field keeps its own inset (a separate field style, follow-up #30142).

Viewed after image: yes (2x, light and dark, above)

Tests (Linux, real Chromium/WebKit via cmux-ci test):

  • Head: checkmark-alignment, project-menu-geometry, picker-row-geometry, quick-model-menu-layout, model-menu-density, access-grants-columns, composer-claude-split and 16 other menu suites pass (336 pass); bun scripts/check-design-tokens.ts and check-menu-metrics.py's web check pass. The only reds are grid-lines transcript.actions/after-steer (warn-level), which fail the same way on base.
  • Base with this PR's tests: checkmark-alignment and project-menu-geometry fail on every menu (17 tests).

Follow-ups from review: #30142.

Gallery: ui.menu/open, ui.select/open, ui.context-menu/open, ui.combobox/open, agent-pane.composer-plus-menu/balanced, agent-pane.header-tools/menu-open, agent-pane.project-chooser/open-current

Agent session: agent session

🤖 Generated with Claude Code

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions github-actions Bot added the risk:low Risk tier (docs/ci/risk-tiers.md) label Oct 29, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Found 14 test failures on Blacksmith runners:

Failures

Test View Logs
test/composer-menu-dismiss.test.ts/composer-menu-dismiss.test View Logs
test/composer-menu-dismiss.test.ts/composer-menu-dismiss.test View Logs
test/gallery-agent-pane-entries.test.ts/gallery-agent-pane-entries.test View Logs
test/gallery-agent-pane-entries.test.ts/gallery-agent-pane-entries.test View Logs
test/incoming-message-disclosure-browser.test.ts/
incoming-message-disclosure-browser.test
View Logs
test/incoming-message-disclosure-browser.test.ts/
incoming-message-disclosure-browser.test
View Logs
test/thread-minimap-feel.test.ts/thread-minimap-feel.test View Logs
test/thread-minimap-feel.test.ts/thread-minimap-feel.test View Logs
test/thread-rail-fast-scroll-edges.test.ts/thread-rail-fast-scroll-edges.test View Logs
test/thread-rail-fast-scroll-edges.test.ts/thread-rail-fast-scroll-edges.test View Logs

...and 4 more test failures. View all on Blacksmith

Blacksmith runners detected OOM events on the following jobs:

Job Details
web / react-apps-base-check (4) View Job

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@cmux-bot

cmux-bot Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 95a39fa: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr27616 -f ref=lane/grid-menu-lines -f platform=macos -f backend_mode=local

Probably yours: new-tab-field-on-art.test.ts, new-tab-field-on-art.test.ts, composer-menu-dismiss.test.ts and 1 more fails here but not on main's latest full suite. Seen on other PRs too (likely flaky): agent-pane-ctrl-b-background.test.ts, incoming-message-disclosure-browser.test.ts, incoming-message-disclosure-browser.test.ts and 11 more.

CI failed on 95a39fac6a (run 41872856632 attempt 1): 4 code, 1 unknown.

Job Verdict Why
web / react-apps-base-check (6) code a web test failed
web / react-apps-base-check (4) code a web test failed
web / react-apps-base-check (8) code a web test failed
web / react-apps-base-check (7) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs agent-pane-ctrl-b-background.test.ts no answer: after the request's 10 s deadline a notice says the work still runs: failed (job)
  • new in this PR new-tab-field-on-art.test.ts the New Tab field on a wallpaper theme in chromium > a suggestion row is a popup row: a menu row's h...: failed (job)
  • new in this PR new-tab-field-on-art.test.ts the New Tab field on a wallpaper theme in webkit > a suggestion row is a popup row: a menu row's hei...: failed (job)
  • seen on other PRs incoming-message-disclosure-browser.test.ts the chat's last row, opened with the view at its end, pushes the text up; closed, stays on its pixel: failed (job)
  • seen on other PRs incoming-message-disclosure-browser.test.ts a delivered message and a waiting one draw the same line: chevron after the words, actions on hover: failed (job)
  • seen on other PRs thread-rail-fast-scroll-edges.test.ts chromium: the list moved past its drawn rows still shows its resting ticks: failed (job)
  • seen on other PRs thread-rail-fast-scroll-edges.test.ts webkit: the list moved past its drawn rows still shows its resting ticks: failed (job)
  • seen on other PRs thread-rail-pending-load.test.ts hovering a far pending tick shows that prompt's words: failed (job)
  • seen on other PRs thread-rail-pending-load.test.ts clicking a far pending tick lands on its prompt in one read, and no tick moves: failed (job)
  • seen on other PRs thread-rail-pending-load.test.ts a sweep across many pending ticks reads the index at most once: failed (job)
  • ... 8 more in the job logs
Matched log lines
web / react-apps-base-check (6): (fail) no answer: after the request's 10 s deadline a notice says the work still runs [20977.00ms]
web / react-apps-base-check (4): (fail) the chat's last row, opened with the view at its end, pushes the text up; closed, stays on its pixel [1930.96ms]
web / react-apps-base-check (8): (fail) webkit: agent-pane.new-tab reasoning-chip at 300 px: with a menu open, one press on another chip opens that one [7255.76ms]
web / react-apps-base-check (7): (fail) thread minimap feel (Chromium) > a click lands the prompt's bubble 35 px down, near or far, drawn or not [845.85ms]

Not re-run automatically: web / react-apps-base-check (6), web / react-apps-base-check (4), web / react-apps-base-check (8), web / react-apps-base-check (7), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; a job it gathers is red on this change (its line here); do not merge until green; see lane-rules
red: web / react-apps-base-check (4); NEW webview test reds: test/accent-glass-invariants-4.test.ts > no orange or system accent and no opaque glass on the gallery stages (part 4 of 6); test/new-tab-list-columns.test.ts > (unnamed); test/claude-reasoning-default.test.ts; do not merge until green; see lane-rules
red: web / react-apps-base-check (6); NEW webview test reds: test/new-tab-field-on-art.test.ts > the New Tab field on a wallpaper theme in webkit > a suggestion row is a popup row: a menu row's height, the row radius and the popup inset; test/new-tab-field-on-art.test.ts > the New Tab field on a wallpaper theme in chromium > a suggestion row is a popup row: a menu row's height, the row radius and the popup inset; do not merge until green; see lane-rules
red: web / react-apps-base-check (7); NEW webview test reds: test/composer-inline-reorder.browser.test.ts > a press on a thumbnail's centre drags it past the next one; the × shows only on hover; test/composer-footer-harness.test.ts > (unnamed); test/composer-chip-plain-rest.test.ts > (unnamed) (+2 more); do not merge until green; see lane-rules
red: web / react-apps-base-check (8); NEW webview test reds: test/gallery-agent-pane-entries.test.ts > (unnamed); do not merge until green; see lane-rules
red: web / react-apps-check; a job it gathers is red on this change (its line here); do not merge until green; see lane-rules

Gallery before/after for 95a39fa: 7 states rendered, 8 images differ (picked by the Gallery: line in the PR body). Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41872856284 -R manaflow-ai/cmux -n gallery-advisory-27616-95a39fac6ab20c8697fd851eeb6e092abee85ed9 (then read gallery-review.json)

States
State Theme Status Diff Picked by
ui.menu/open Apple System Colors Light changed 0.0947% pr-body
ui.menu/open Apple System Colors changed 0.0935% pr-body
ui.select/open Apple System Colors Light unchanged 0% pr-body
ui.select/open Apple System Colors unchanged 0% pr-body
ui.context-menu/open Apple System Colors Light unchanged 0% pr-body
ui.context-menu/open Apple System Colors unchanged 0% pr-body
ui.combobox/open Apple System Colors Light changed 2.5% pr-body
ui.combobox/open Apple System Colors changed 2.33% pr-body
agent-pane.composer-plus-menu/balanced Apple System Colors Light changed 4.48% pr-body
agent-pane.composer-plus-menu/balanced Apple System Colors changed 4.43% pr-body
agent-pane.header-tools/menu-open Apple System Colors Light unchanged 0% pr-body
agent-pane.header-tools/menu-open Apple System Colors unchanged 0% pr-body
agent-pane.project-chooser/open-current Apple System Colors Light changed 6.35% pr-body
agent-pane.project-chooser/open-current Apple System Colors changed 6.29% pr-body

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

@github-actions github-actions Bot added risk:normal Risk tier (docs/ci/risk-tiers.md) and removed risk:low Risk tier (docs/ci/risk-tiers.md) labels Oct 29, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Awareness: cmux#28530 merged as c8a6942 and changed the shared ui/Select rules (checkmark gutter, 28px rows on the menu row token, menu aligned to the trigger's left edge, glass tint and blur). This PR also changes popupSurface.css and ui.css, so please merge base and check the menu grid doesn't collide with those rules. Spec: design/settings.md in leo-workspace (teamleaderleo/leo-workspace#1746). Comment only; nothing pushed here.

teamleaderleo and others added 3 commits October 31, 2026 19:22
Resolves popupSurface.css (keeps base's data-popup-shift rule beside the shared
menu columns) and composerLocation.css (the allowed rules keep #27579's text and
trailing columns, now from the shared menu row). Leaves the model picker
(.acpmux-quick-menu and its side menus) on its settled columns from #29791: its
running row's check shares the ⌘N column, so this PR no longer moves it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0
…oken baseline

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0
…row has an icon; Claude Code pickers keep their trailing check

- A title with no icon column starts at iconX (15), or right after the check at 22 in a menu with
  a state column (schemas/menu-metrics; a select's 22 from #28530 / design/settings.md).
- The project chooser's own lead icon (#28590's .acpmux-project-lead) sits on the icon column.
- The model picker (#29791), its effort menu and the mode menu keep the chosen row's check in its
  number's place at the trailing edge (Leo 2026-10-19; composer-claude-split.test.ts), so they
  stay out of the shared grid and their files are base's. Row defaults stay for menus outside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0
…text column right-to-left

Review (codex gpt-6-astra, BLOCK at 2e59359): the shared heading rule used physical
four-value padding. checkmark-alignment now measures headings and runs each menu
right-to-left too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, fast, via review-router): BLOCK at 2e59359

  • [blocking] RTL group headings lose alignment — popupSurface.css gives .ui-menu-group-label and .acpmux-menu-header physical padding: block trailing block leading, while rows use logical padding. In RTL, headings therefore start 12 px from the right edge, irrespective of the menu’s text column. A plain grouped menu previously had matching symmetric insets; now its headings and rows diverge. Use padding-block and padding-inline, and test grouped menus under dir="rtl".

  • [follow-up] Geometry tests leave important claims unchecked — Both changed suites launch Chromium only. They measure left coordinates, accept any row height ≥28, and omit heading alignment, trailing inset, vertical check alignment, and excluded-picker geometry. Add RTL and WebKit cases, exact heights for single-line rows, and assertions for those columns. Existing WebKit suites passing does not directly establish this geometry contract.

  • [follow-up] The lint guard does not enforce surface delegation — check-menu-metrics.py initializes migrated = set() without populating it. Consequently, ordinary surface selectors are skipped even in the three additional files it scans. Reintroducing their literal row padding would pass. Populate the migrated selectors and add a negative fixture demonstrating that enforcement.

The supplied LTR measurements match the intended leading columns and highlight metrics. The shared selectors outrank the ordinary ui.css/styles.css rules and zero-specificity :where() defaults. All three picker exclusions remain effective despite .ui-menu; modern Chromium and WebKit support the selector syntax. The RTL heading defect prevents a clean native-menu polish verdict.

Fixed the blocking finding in the next commit; the two follow-ups stay follow-ups.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, fast, via review-router): SHIP at 872fc4e

The prior RTL heading blocker is fixed: headings now use logical padding-block/padding-inline, and selector specificity is sufficient. Excluded picker menus retain their geometry.

[follow-up] The alignment suite runs Chromium only; WebKit behavior for :has()/:not() remains unverified.

[follow-up] Height checks only require >= 28, not exact 28px/44px geometry. Project geometry remains light/LTR only.

[follow-up] check-menu-metrics.py leaves migrated = set() empty and only scans one exact shared selector prefix, missing independently scoped CSS rules.

[follow-up] Removing the static .ui-menu-check contract test leaves direct coverage gaps across the three CSS bundles.

Follow-ups: the [follow-up] items above, plus the earlier ones from the BLOCK at 2e59359 (fixed), go to one issue for the menu-grid lane.

…parator inset, not the text column

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, fast, via review-router): SHIP at 1ee9d81

Delta since the SHIP at 872fc4e (the project chooser hairline back on the separator inset): no findings. Follow-ups: #30142.

teamleaderleo and others added 2 commits November 1, 2026 22:49
# Conflicts:
#	webviews/src/agent-session/acpmux/styles.css
#	webviews/src/ui/ContextMenu.tsx
…ng checks

#28611 (now on base) excludes .acpmux-scope-list from the shared menu grid; this
PR's rules matched it and moved ScopeMenu's and ChatFilterMenu's checks to the
leading state column. Exclude it here too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-90f18511b4bf53b41d20
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Merged feat-cmux-next (4453d0b) into this branch, which now carries #28611's menu grid. Conflicts: ui/ContextMenu.tsx took base's version (a superset of this PR's change), and the .ui-context-menu .ui-menu-item line in acpmux/styles.css took base's line. This PR's other styles.css changes stayed.

Review (codex gpt-6-astra high, fast, via review-router): BLOCK at 7352039

Fix 5941893: every one of this PR's selectors also excludes .acpmux-scope-list.

Review (codex gpt-6-astra high, fast, via review-router): SHIP at 5941893
Follow-ups: #31479 (consolidate the two rule sets, align the exclusions, add scope-menu coverage).

Tests at 5941893 (cmux-ci test, Linux Chromium and WebKit): typecheck passes and check:design-tokens passes. The menu suites (menu, checkmark, picker, select, combobox, access-grants, composer-claude-split, popup-surface, subtle-elevation, scope) had 906 pass and 31 fail. All 30 distinct failing names fail the same way on base 4453d0b with the same command (869 pass, 31 fail). grid-lines.test.ts had 160 pass and 0 fail at the merge.

@teamleaderleo
teamleaderleo marked this pull request as ready for review November 2, 2026 00:12
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Orphaned: only the sweep's base merge since, and no lane holds a lease on it. The orphan sweep could not merge feat-cmux-next in: conflicts in webviews/src/ui/popupSurface.css. Listed for a lane to resolve.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Batch 1 composer-menu migration is in #34299. It consumes the shared grid metrics from this draft and moves the remaining composer Picker, slash, and mention lists onto ui/Menu and ui/Listbox while leaving nativePopup direction untouched. Please treat #34299 as the composer integration that supersedes the remaining work here; this PR remains yours.

teamleaderleo and others added 3 commits November 3, 2026 16:55
popupSurface.css: both sides appended at the end of the file. Keep base's
shared scroll-edge fade (#32836) and put the menu grid after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-ac5053f7854c8635a4d0

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 95a39fac Deployed Nov 4, 2026 by teamleaderleo via wait for same-key tree publisher #112475
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant