Skip to content

Solid themed toasts, "New Tab" titles, no raw workspace ids - #19759

Merged
teamleaderleo merged 6 commits into
feat-cmux-nextfrom
op-next-theme/toasts
Oct 12, 2026
Merged

teamleaderleo merged 6 commits into
feat-cmux-nextfrom
op-next-theme/toasts

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Toasts in cmux-next were cramped, translucent glass, and a closed New Tab page said Closed “about:blank”. Now every toast uses one solid, themed component, tabs keep their strip names everywhere, and no error shows a raw id.

The component (CmuxNextDesign/Toast)

  • The surface is opaque: the theme's overlay fill (ThemeTokens.opaqueOverlayFill at ChromeTunables.opaqueOverlayLift, the same fill Reduce Transparency uses), pinned on every Mac. Palette.popupSurface isn't on base yet; a comment marks where to swap it in.
  • Corners use the popups' 8 pt radius (PopupStyle.standard), not a capsule, and the toast casts the popups' one subtle shadow.
  • Padding is 8 pt vertical and 12 pt leading, with 12 pt before the action. Undo is a full-strength emphasized text button.
  • CmuxToastCenter already did placement (bottom-center, 24 pt up), stacking (three per window), auto-dismiss on DemandTimer and the hover hold; tests now cover them.

Toasts routed through it

  • Refusal HUD: RefusalHUD, the capsule that said "no workspace ", is now a toast with id refusal.
  • Feed and Tasks rejects: FeedToast is deleted. The Feed reject and the Tasks pane's reject overlay go through a new cmuxToast(id:message:onDismiss:) SwiftUI modifier.
    • onDismiss runs on the next main-actor turn whenever the toast ends, including when a newer toast pushes it out of the stack, so the same reject shows again.
    • It also runs when the view is dismantled, so a reopened panel doesn't replay an old reject.
  • Already on CmuxToastCenter, now with the new look: closed tab, group and workspace close or undo, pin, icon history, tab icon, room deleted, remote forget, keymap, CLI install, cloud move and result, recovery notice, file recovery, browser, bookmark and password imports, classic import, and surface zoom.
  • No web page in webviews/src shows a toast.

Tab titles

  • TabTitleResolver moves the strip's title logic out of PaneController. It covers the New Tab page (or History), agent chats, Home conversations, page and app tabs, and incognito tabs.
  • Three places now use it: the strip, the sidebar's tab rows (SidebarBridge passes it as SidebarMapping's tabTitle) and the closed-tab toast, from both a pane close and a tab-group close.
  • Only a browser tab or a real New Tab page becomes "New Tab". A chat or a page tab keeps its own name, even though its record is titled about:blank.

No raw ids

  • 14 refusals that named an object id now say what happened in plain words, for example "That tab is no longer open.", "That workspace is no longer open." and "That window is no longer open."
  • They cover the workspace, workspace group, tab, pane, a pane's workspace, a tab's content, screen, closed item, column, a pane's daemon handle, open and saved tab groups, a workspace's panes, window and screen group.
  • These messages reach the toast, the action not-found paths and the socket's not_found.
  • The new keys in Refusals.xcstrings and Screens.xcstrings are translated into all 21 locales in each catalog, and the old keys are removed.

Testing

cmux-ci run --class light --script scripts/ci/run-swift-testing-suites.sh --arg Packages/macOS/CmuxNext:

First round

  • Red, at eb65fddc8077c87d9bc59eae7637a0d2d25a81cf: CmuxToastSurfaceTests and ToastCopyTests failed on assertions: a glass material instead of opaque, a 10 pt radius, Closed “about:blank”, and no workspace ws_….
  • The placement and hover-hold tests already passed on base; they pin existing behavior.

Review round

  • Red, at 09c5f377c1bb4d5b59614d3b96a3e48377de4c8d (tests only): the build failed because the new test API (CmuxToastAnchorView.center and dismantle, TabTitleResolver, SidebarMapping's tabTitle) didn't exist yet. These tests never failed on an assertion before the fix.
  • ToastCopyTests now checks four things:
    • a chat, a diff page tab, a New Tab page and a blank browser tab keep their strip names in the sidebar rows and in the group-close toast;
    • 15 refusal reasons never contain a sample id.
  • CmuxToastModifierTests checks that a reject pushed out of the stack, and one left behind by a closed panel, clears its model.
  • Green, at d0dbac151ae71aa0ed61e563782ae880f59cc888: all 141 suites passed, including those three suites and HeaderDiffPlacementTests.

Local checks

  • check-concurrency.sh (1 hit), check-theme-scope.sh (15) and crash_ratchet.py (5 modules) match base; none of the hits are in this change.
  • check-system-blue.py and check-no-godfiles.sh pass.
  • lint-ios-package-conventions.sh flags only the two namespace-type errors already on base (CommandRetentionSetting, AgentPaneWarmup).
  • localization_catalog.py check reports nothing for the new keys.

Not verified: there's no live capture, and the Feed and Tasks panel toasts haven't been checked in a running app.

Changelog

Changed: Toasts are a solid, theme-colored card at the bottom center of the window. A closed New Tab page is called "New Tab", chats and pages keep their names in the sidebar and in toasts, and errors no longer show raw ids.

🤖 Generated with Claude Code

teamleaderleo and others added 3 commits October 11, 2026 23:48
A closed New Tab page's toast reads "New Tab", the toast is an opaque
theme surface with a small radius at the bottom center, hover holds it,
and the no-workspace refusal carries no raw id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The toast is an opaque theme surface (the Reduce Transparency overlay fill,
pinned) with the popups' 8 pt radius and shadow, roomier padding and a
full-strength Undo. Refusals (the old capsule HUD) and the Feed and Tasks
panels' rejects now go through CmuxToastCenter, the latter via a
cmuxToast SwiftUI modifier.

A closed New Tab page's toast names it as its strip does, and one shared
rule (TabItemMapping.shownTitle) turns empty or about:blank/newtab titles
into "New Tab" for toasts and sidebar tab rows. The no-workspace and
no-workspace-group refusals are sentences without the raw id, in every
catalog locale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 0a26fe02-8b1e-4228-8285-34143f0e73e7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Not verified: macOS jobs did not run: compile and app tests were skipped on 795e4f22a5; ci-status is green without them.

CI passes on 795e4f22a5 (run 38217469227 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

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.

teamleaderleo and others added 3 commits October 12, 2026 00:16
Sidebar tab rows and the group-close toast name an agent chat, a diff
page tab, a New Tab page and a blank browser tab as their strip does.
A Feed/Tasks reject pushed out of the toast stack, or left by a closed
panel, clears its model. No refusal about a missing object shows its id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TabTitleResolver pulls the strip's title resolution out of PaneController
(New Tab page, agent chat, Home conversation, page and app tabs, incognito)
and the strip, the sidebar's tab rows (SidebarBridge -> SidebarMapping
tabTitle) and the closed-tab toasts (pane and tab-group close) all use it.
Only browser tabs and real New Tab pages become "New Tab";
TabItemMapping.shownTitle, which renamed every chat and page tab, is gone.

cmuxToast now clears its model on every end of the toast, eviction by the
stack limit included, on the next main-actor turn, and when its view is
dismantled, so a repeated reject shows again and a reopened panel does not
replay an old one.

Twelve more refusals that named a raw id (tab, pane, screen, closed item,
column, tab groups, window, screen group, ...) are now id-free sentences
in every catalog locale; the old keys are gone. The debug.window comment
describes the refusal toast.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo merged commit ac28337 into feat-cmux-next Oct 12, 2026
83 checks passed
@teamleaderleo
teamleaderleo deleted the op-next-theme/toasts branch October 12, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant