Skip to content

Prioritize mobile toolbar controls over long titles - #7229

Closed
azooz2003-bit wants to merge 8 commits into
mainfrom
feat-toolbar-priority-layout
Closed

azooz2003-bit wants to merge 8 commits into
mainfrom
feat-toolbar-priority-layout

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jul 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Replace the mobile toolbar title width cap with semantic SwiftUI layout priorities.
  • Give the title a compressible toolbar role and trailing controls a fixed toolbar role.
  • Add an inline workspace UI regression that asserts a long title yields before the chat and terminal buttons.

Verification

  • xcodebuild test -scheme CmuxMobileShellUI -destination 'platform=iOS Simulator,id=5AD831AA-8F8C-42F6-BA3E-DA9A0D971C26' -derivedDataPath /tmp/cmux-tprio-pkg -only-testing:CmuxMobileShellUITests/WorkspaceToolbarLayoutPriorityTests
  • xcodebuild test -workspace ios/cmux.xcworkspace -scheme cmux-ios -configuration Debug -destination 'platform=iOS Simulator,id=5AD831AA-8F8C-42F6-BA3E-DA9A0D971C26' -derivedDataPath /tmp/cmux-ios-tprio-uitests -only-testing:cmuxUITests/cmuxUITests/testInlineWorkspaceLongTitleYieldsToTrailingToolbarControls
  • ./scripts/reload.sh --tag tprio
  • ./ios/scripts/reload.sh --tag tprio --simulator cmux-tprio-verify --no-setup

Dogfood

  • macOS tag: http://127.0.0.1:17320/tprio
  • iOS tag: tprio on simulator cmux-tprio-verify (5AD831AA-8F8C-42F6-BA3E-DA9A0D971C26)
  • Screenshot evidence: /tmp/cmux-tprio-evidence/inline-workspace-long-title-final.png

Notes

  • Full package suite still has unrelated existing WorkspaceMacSelectionTests failures around pending machine selection restore state.
  • Existing workspace-detail long-title UI tests currently fail before toolbar assertions because the preview harness does not render MobileWorkspaceTitleMenu.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Prioritize mobile toolbar controls over long titles on iOS so chat and terminal buttons always stay visible. Replace width caps with a shared priority toolbar across inline previews and production, with tests that enforce truncation and title height fitting.

  • Refactors

    • Removed width-cap/geometry code; added MobileToolbarPriorityHost, MobileToolbarItemLayoutRole, and shared MobileWorkspacePriorityToolbar.
    • Moved WorkspaceDetailView toolbar into .principal with prioritized back/title/trailing clusters; inline preview now uses the same toolbar and fixed-size trailing controls.
    • Simplified WorkspaceTitleMenu to a compressible title; extracted WorkspaceDetailPreviewWorkspaceBuilder with stable action capabilities.
  • Bug Fixes

    • Long titles now truncate before chat and terminal controls in inline previews and production workspace detail.
    • Tightened UI tests: added inline and production coverage for truncation, and a height-fit check so the compact title never grows taller than nearby controls.

Written for commit ad2ab57. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Introduced improved mobile workspace header toolbar composition with explicit layout prioritization for back, title, and trailing controls, ensuring long titles stay readable.
  • Bug Fixes

    • Fixed long workspace title layout to correctly yield/truncate around back and trailing controls (including inline toolbars and chat-toggle combinations), reducing overlap/clashing.
  • Tests

    • Added/updated UI regression checks for “title yields to trailing controls,” including inline and screenshot coverage, and refreshed toolbar title-height fitting assertions.

@vercel

vercel Bot commented Jul 3, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 3, 2026 6:09am
cmux-staging Building Building Preview, Comment Jul 3, 2026 6:09am

@coderabbitai

coderabbitai Bot commented Jul 3, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces width-based toolbar title sizing with role-based layout priorities across workspace toolbars, updates UI regression coverage for title/trailing control spacing, and centralizes delayed-terminal preview workspace construction in shared helpers.

Changes

Toolbar title and trailing control layout

Layer / File(s) Summary
Layout roles and priority host
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileLeadingToolbarTitleWidth.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarPriorityHost.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileWorkspacePriorityToolbar.swift
Removes MobileLeadingToolbarTitleWidth and adds role-based layout priority types plus a toolbar wrapper that applies per-slot priorities.
WorkspaceTitleMenu priority behavior
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift
Moves the title menu into MobileToolbarPriorityHost(role: .compressibleTitle) and changes the label sizing from capped width framing to priority-based clipping.
Workspace toolbar wiring
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift, Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AgentChatDemoScreen.swift
Removes contentWidth measurement, updates WorkspaceTitleMenu construction, and rehosts trailing controls with the new priority wrapper.
Toolbar geometry regressions
ios/cmuxUITests/cmuxUITests.swift, Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/MobileLeadingToolbarTitleWidthTests.swift
Adds UI assertions for title yielding and compact-toolbar height behavior, and removes the old unit tests for the deleted width-cap helper.

Preview workspace construction helpers

Layer / File(s) Summary
Create delayed terminal preview helper
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift
Adds a shared workspace constructor and applies actionCapabilities during initial and delayed preview workspace creation.
Delayed terminal preview helper
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailDelayedTerminalPreviewView.swift
Adds a shared workspace constructor and applies actionCapabilities during initial and injected delayed preview workspace creation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • manaflow-ai/cmux#7092: Both PRs adjust the iOS workspace title toolbar layout in AgentChatDemoScreen.swift and WorkspaceDetailView.swift.
  • manaflow-ai/cmux#7097: Both PRs refactor WorkspaceTitleMenu and its toolbar wiring, including title sizing and caller updates.
  • manaflow-ai/cmux#7116: Both PRs touch WorkspaceTitleMenu and the workspace toolbar layout path, but in opposite directions on the width-cap approach.
🚥 Pre-merge checks | ✅ 25
✅ Passed checks (25 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed Touched code is UI-only/main-actor-bound; new toolbar views and preview helpers add no unsafe Sendable refs or background store access.
Cmux Swift Blocking Runtime ✅ Passed Only test helpers and #if DEBUG preview scaffolding use polling/sleeps; touched production Swift files are layout-only and add no blocking sync.
Cmux Browser Automation Off-Main ✅ Passed Diff only touches mobile toolbar UI and UI tests; no browser.* socket commands, mainActor routing, or worker-policy changes were modified.
Cmux Expensive Synchronous Load ✅ Passed Patch only changes toolbar layout/preview helpers; searches found no RestorableAgentSessionIndex.load, Data(contentsOf:), or JSON parsing in touched files.
Cmux Cache Substitution Correctness ✅ Passed PR only changes toolbar layout, previews, and UI tests; no cached/opportunistic value replaces an authoritative read in persistence/history/undo/snapshot paths.
Cmux No Hacky Sleeps ✅ Passed PASS: Only Swift app/UI-test files changed; no TS/JS/shell/runtime scripts were modified, and the added waits are test-only scaffolding.
Cmux Algorithmic Complexity ✅ Passed PASS: The PR only swaps toolbar sizing for layout-priority views; changed collection work is limited to debug/test preview code and single linear workspace updates, with no nested rescans or hot-pa...
Cmux Swift Concurrency ✅ Passed Diff only refactors SwiftUI toolbar layout and XCTest assertions; no new DispatchQueue, Combine, completion-handler, or fire-and-forget Task patterns were introduced.
Cmux Swift @Concurrent ✅ Passed No changed async work needs @concurrent; the only new async flows are UI-bound .task/Task { @mainactor in ... } preview updates and stay on MainActor.
Cmux Swift File And Package Boundaries ✅ Passed New production files are tiny UI/layout helpers; the only oversized touched file (WorkspaceDetailView, 684 lines) was pre-existing and only got a small toolbar refactor.
Cmux Swiftpm Lockfiles ✅ Passed PR changes only touched source/tests; no Package.swift, Package.resolved, .gitignore, xcodeproj, or workflow files changed, so the SwiftPM lockfile rule wasn’t triggered.
Cmux Swift Logging ✅ Passed The commit changes only AgentChatDemoScreen and tests; no added print/debugPrint/dump/NSLog/Logger appears in the diff.
Cmux User-Facing Error Privacy ✅ Passed The PR only refactors toolbar layout; no production user-facing error/alert/recovery text was added or changed.
Cmux Full Internationalization ✅ Passed PASS: the touched production Swift files only change layout/toolbar structure; no new user-facing text, locale keys, or catalog edits appear, and the new literals are developer-only identifiers/tests.
Cmux Swiftui State Layout ✅ Passed PASS: the PR removes geometry-based title sizing and adds only pure layout wrappers; full-range scans found no new ObservableObject/@published or render-time state mutation.
Cmux Architecture Rethink ✅ Passed PASS: The diff swaps width-cap logic for shared priority toolbar views with clear owners/invariants; any polling/sleeps are confined to DEBUG previews or UI tests.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed Touched files are toolbar views/tests only; no NSWindow/NSPanel/WindowGroup or cmuxAuxiliaryWindowIdentifiers changes, so the auxiliary-window rule doesn’t apply.
Cmux Source Artifacts ✅ Passed All changed paths are intentional Swift source/test files; no logs, screenshots, temp dirs, caches, or other artifact paths appear in the PR diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed Diff only replaces width-cap logic with layout-priority helpers; no new debug/Test-only accessors or seam-like members were added in Sources.
Cmux No Ambient Global State ✅ Passed The PR adds only constructable SwiftUI types and private file-scope helpers/constants; no new global mutable state, singletons, or static-helper namespaces appear.
Title check ✅ Passed The title clearly summarizes the main change: prioritizing toolbar controls over long titles.
Description check ✅ Passed The description covers summary and testing, but it lacks the required Demo Video section and a complete checklist.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-toolbar-priority-layout

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift`:
- Around line 29-33: The `fittedLabel` view in `WorkspaceTitleMenu` applies a
redundant `layoutPriority` that has no effect because it is the only content
inside the `Menu`/`Button`; remove the inner
`.layoutPriority(MobileToolbarItemLayoutRole.compressibleTitle.swiftUILayoutPriority)`
from `fittedLabel` and keep the priority only on `MobileToolbarPriorityHost`,
which is the place that governs toolbar item compression.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 737f236a-9242-42f5-8679-830e8b632e6a

📥 Commits

Reviewing files that changed from the base of the PR and between fa21e6a and 799b9fc.

📒 Files selected for processing (7)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AgentChatDemoScreen.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileLeadingToolbarTitleWidth.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/MobileLeadingToolbarTitleWidthTests.swift
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/WorkspaceToolbarLayoutPriorityTests.swift
  • ios/cmuxUITests/cmuxUITests.swift
💤 Files with no reviewable changes (2)
  • Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/MobileLeadingToolbarTitleWidthTests.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileLeadingToolbarTitleWidth.swift

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 7 files

Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Jul 3, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Replaces the old width-cap geometry approach (measuring contentWidth via onGeometryChange and computing a pixel cap) with SwiftUI layoutPriority applied inside a shared MobileWorkspacePriorityToolbar HStack, so the title genuinely competes with — and yields to — the back and trailing controls as true layout siblings. The production toolbar in WorkspaceDetailView and the inline-preview toolbar in AgentChatDemoScreen are unified on the same compositor.

  • Core layout change: MobileWorkspacePriorityToolbar places back (priority 1, fixed), title (priority −1, flexible), and trailing (priority 1, fixed) in one HStack inside .principal, making the title the sole compressible element; MobileLeadingToolbarTitleWidth and all contentWidth state are removed.
  • Shared preview infra: WorkspaceDetailPreviewWorkspaceBuilder is extracted to give both delayed-terminal preview views stable actionCapabilities on their fixture workspaces.
  • Test updates: Width-cap unit tests are deleted; UI tests gain an inline-preview long-title regression, updated production assertions using assertToolbarTitleYieldsToTrailingControls, and the height-fit check is refined from a symmetric ±2 tolerance to a one-sided ≤+4 overflow check.

Confidence Score: 5/5

The change is safe to merge; it removes stateful geometry measurement code and replaces it with a well-scoped layout-priority HStack, with no regressions on actor isolation, blocking primitives, or ambient global state.

The production changes are narrowly scoped to toolbar composition in CmuxMobileShellUI. Removing the onGeometryChange/contentWidth state loop is a net improvement to layout stability. The new MobileWorkspacePriorityToolbar correctly places all three toolbar items as true HStack siblings, so the layoutPriority competition is structurally valid. The only finding is WorkspaceDetailPreviewWorkspaceBuilder landing in production Sources under #if DEBUG with no production caller, which is a style concern consistent with the project's existing preview-view pattern.

No files require special attention; WorkspaceDetailPreviewWorkspaceBuilder.swift has a minor placement concern (debug-only type in production Sources) but poses no runtime risk.

Important Files Changed

Filename Overview
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileWorkspacePriorityToolbar.swift New HStack-based toolbar compositor; back, title, and trailing are true siblings so .layoutPriority competition is real and correct here.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift Small enum mapping semantic roles to SwiftUI layout priority values; straightforward.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarPriorityHost.swift Thin ViewBuilder wrapper that applies a role's layout priority to its content; clean.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift Simplified by removing width-cap math; now delegates compressibility to MobileToolbarPriorityHost; redundant inner layoutPriority calls were already noted in prior review threads.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift Toolbar consolidated from three separate ToolbarItems into a single principal MobileWorkspacePriorityToolbar; removes GeometryReader-adjacent state, which is a layout stability improvement.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailPreviewWorkspaceBuilder.swift New file in production Sources entirely wrapped in #if os(iOS) && DEBUG; a debug-only helper with no production caller that belongs in the test target or a debug support module.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AgentChatDemoScreen.swift Switches inline-workspace toolbar to use MobileWorkspacePriorityToolbar; removes contentWidth GeometryChange measurement; title and trailing are properly scoped non-optional DemoStack parameters.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift Refactored to use WorkspaceDetailPreviewWorkspaceBuilder for stable actionCapabilities on preview workspaces; all logic remains #if DEBUG gated.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailDelayedTerminalPreviewView.swift Same builder migration as CreateDelayed variant; no functional logic changes beyond using the shared builder.
Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/MobileLeadingToolbarTitleWidthTests.swift Deleted together with MobileLeadingToolbarTitleWidth; tests covered now-removed width-cap math.
ios/cmuxUITests/cmuxUITests.swift Adds inline-preview long-title regression test, updates production assertions to use assertToolbarTitleYieldsToTrailingControls, loosens height tolerance from ±2 to ≤+4, and replaces centered-separation check with a yield/truncate check.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[WorkspaceDetailView / AgentChatDemoScreen]
    A --> B[ToolbarItem placement: .principal]
    B --> C[MobileWorkspacePriorityToolbar]
    C --> D[back layoutPriority 1 fixedSize]
    C --> E[title layoutPriority -1 maxWidth .infinity]
    C --> F[trailing layoutPriority 1 fixedSize]
    E --> G[WorkspaceTitleMenu]
    G --> H[MobileToolbarPriorityHost role: .compressibleTitle]
    H --> I[Menu or Button fittedLabel]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[WorkspaceDetailView / AgentChatDemoScreen]
    A --> B[ToolbarItem placement: .principal]
    B --> C[MobileWorkspacePriorityToolbar]
    C --> D[back layoutPriority 1 fixedSize]
    C --> E[title layoutPriority -1 maxWidth .infinity]
    C --> F[trailing layoutPriority 1 fixedSize]
    E --> G[WorkspaceTitleMenu]
    G --> H[MobileToolbarPriorityHost role: .compressibleTitle]
    H --> I[Menu or Button fittedLabel]
Loading

Reviews (5): Last reviewed commit: "fix: move workspace preview builder to o..." | Re-trigger Greptile

Comment on lines 29 to +33
private var fittedLabel: some View {
let cap = MobileLeadingToolbarTitleWidth(
contentWidth: contentWidth,
hasBackButton: hasBackButton,
hasTrailingCluster: hasTrailingCluster,
hasChatToggle: hasChatToggle
).cap

return label()
.frame(
minWidth: min(MobileLeadingToolbarTitleWidth.floor, cap),
maxWidth: cap,
alignment: .leading
)
label()
.layoutPriority(MobileToolbarItemLayoutRole.compressibleTitle.swiftUILayoutPriority)
.fixedSize(horizontal: false, vertical: true)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The .layoutPriority(-1) applied to label() here is redundant. fittedLabel is used as the sole child inside a Menu.label or Button.label closure — there are no sibling views in that container to compete with, so the priority modifier has no observable effect. The effective layout priority is already established by MobileToolbarPriorityHost.body (line 62), which applies role.swiftUILayoutPriority to the whole Menu/Button. Removing the inner application keeps the intent readable at a single, correct call site.

Suggested change
private var fittedLabel: some View {
let cap = MobileLeadingToolbarTitleWidth(
contentWidth: contentWidth,
hasBackButton: hasBackButton,
hasTrailingCluster: hasTrailingCluster,
hasChatToggle: hasChatToggle
).cap
return label()
.frame(
minWidth: min(MobileLeadingToolbarTitleWidth.floor, cap),
maxWidth: cap,
alignment: .leading
)
label()
.layoutPriority(MobileToolbarItemLayoutRole.compressibleTitle.swiftUILayoutPriority)
.fixedSize(horizontal: false, vertical: true)
}
private var fittedLabel: some View {
label()
.fixedSize(horizontal: false, vertical: true)
}

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines 36 to 63
enum MobileToolbarItemLayoutRole {
case compressibleTitle
case fixedTrailingControls

var swiftUILayoutPriority: Double {
switch self {
case .compressibleTitle:
return -1
case .fixedTrailingControls:
return 1
}
}
}

struct MobileToolbarPriorityHost<Content: View>: View {
let role: MobileToolbarItemLayoutRole
let content: Content

init(role: MobileToolbarItemLayoutRole, @ViewBuilder content: () -> Content) {
self.role = role
self.content = content()
}

@ViewBuilder
var body: some View {
content
.layoutPriority(role.swiftUILayoutPriority)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 MobileToolbarItemLayoutRole / MobileToolbarPriorityHost may not create the cross-item competition the naming implies. SwiftUI's layoutPriority only establishes relative priority among sibling views inside the same SwiftUI layout container. In an iOS navigation bar, items placed in .topBarLeading (or .principal) and .topBarTrailing are wrapped in separate UIBarButtonItem custom views by UIKit — they are not siblings in any shared SwiftUI layout pass. The host applies layoutPriority(1) to the trailing cluster and layoutPriority(-1) to the title, but because the two live in different UIKit containers there is no SwiftUI container above them to act on those priorities relative to each other.

The title truncates correctly in practice because UIKit's navigation bar layout natively reserves trailing item space before constraining the leading/title area — not because of the SwiftUI priority values. A future author adding a third role value or tweaking the priority number would expect the abstraction to govern the competition, but it doesn't. Consider documenting that the priority modifier here scopes to within each item's own view subtree and that UIKit's inter-placement layout is what prevents title overflow.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread ios/cmuxUITests/cmuxUITests.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift (1)

39-51: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Mark the new pure-value MobileToolbarItemLayoutRole enum nonisolated.

This is a brand-new pure value type (two cases + a computed property, no UI/state dependency). Under this repo's Swift 6 MainActor-by-default isolation, it will implicitly inherit @MainActor unless explicitly marked otherwise, adding unnecessary actor coupling for a value-only utility.

-enum MobileToolbarItemLayoutRole {
+nonisolated enum MobileToolbarItemLayoutRole {
     case compressibleTitle
     case fixedTrailingControls

As per coding guidelines: "Report a failure when the diff introduces or materially expands ... pure value model structs that remain implicitly @MainActor when they should be marked nonisolated."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift`
around lines 39 - 51, The new pure-value MobileToolbarItemLayoutRole enum is
implicitly inheriting MainActor isolation and should be explicitly marked
nonisolated. Update the enum declaration itself, not the swiftUILayoutPriority
property, so this value-only type stays decoupled from UI actor isolation under
Swift 6 MainActor-by-default rules.

Source: Coding guidelines

ios/cmuxUITests/cmuxUITests.swift (1)

2585-2633: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Remove the width-based fallback in this toolbar assertion. ios/cmuxUITests/cmuxUITests.swift:2585-2633 — titleFrameUsesIdealTextWidth can still pass when the title frame is wider than the space before the trailing controls, so the helper may accept the overlap state it is meant to catch. If this is compensating for a simulator/AX quirk, document that explicitly; otherwise keep only the actual separation check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/cmuxUITests/cmuxUITests.swift` around lines 2585 - 2633, The toolbar
assertion helper in assertToolbarTitleYieldsToTrailingControls is still allowing
overlap through the width-based fallback, which can let the bad layout pass.
Remove the titleFrameUsesIdealTextWidth condition and rely on the actual
separation check between the title frame and the first trailing control; if you
must keep any fallback for simulator or AX quirks, make that exception explicit
in the helper and document it in-place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift`:
- Around line 69-92: The MobileWorkspacePriorityToolbar is using
MobileToolbarItemLayoutRole.fixedTrailingControls for the leading back()
control, which is misleading because the role name implies trailing placement.
Update the layout role naming in MobileWorkspacePriorityToolbar to a
position-neutral concept (for example, a fixed control role) and use it
consistently for both back() and trailing() so the semantics match the actual
usage and future maintainers are not confused.

---

Outside diff comments:
In `@ios/cmuxUITests/cmuxUITests.swift`:
- Around line 2585-2633: The toolbar assertion helper in
assertToolbarTitleYieldsToTrailingControls is still allowing overlap through the
width-based fallback, which can let the bad layout pass. Remove the
titleFrameUsesIdealTextWidth condition and rely on the actual separation check
between the title frame and the first trailing control; if you must keep any
fallback for simulator or AX quirks, make that exception explicit in the helper
and document it in-place.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift`:
- Around line 39-51: The new pure-value MobileToolbarItemLayoutRole enum is
implicitly inheriting MainActor isolation and should be explicitly marked
nonisolated. Update the enum declaration itself, not the swiftUILayoutPriority
property, so this value-only type stays decoupled from UI actor isolation under
Swift 6 MainActor-by-default rules.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: add65eb1-aa7d-48a8-951f-f70567689acb

📥 Commits

Reviewing files that changed from the base of the PR and between 799b9fc and 4c584d7.

📒 Files selected for processing (5)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailDelayedTerminalPreviewView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift
  • ios/cmuxUITests/cmuxUITests.swift

Comment thread Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileWorkspacePriorityToolbar.swift`:
- Around line 4-29: The layout role name fixedTrailingControls is misleading
because MobileWorkspacePriorityToolbar uses it for both the leading back()
control and the trailing control, so rename the enum case to a more general
non-compressing/control-priority name and update the
MobileWorkspacePriorityToolbar body plus the matching usage in
WorkspaceTitleMenu.swift. Keep the behavior the same by preserving the current
swiftUILayoutPriority mapping, but make the symbol name reflect that it applies
to any fixed control, not just trailing ones.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ec7ec4bf-2991-471e-8d2b-ffc34d414f47

📥 Commits

Reviewing files that changed from the base of the PR and between 4c584d7 and 023697d.

📒 Files selected for processing (5)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarPriorityHost.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileWorkspacePriorityToolbar.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift
  • ios/cmuxUITests/cmuxUITests.swift
💤 Files with no reviewable changes (1)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceTitleMenu.swift

Comment on lines +4 to +29
struct MobileWorkspacePriorityToolbar<Back: View, Title: View, Trailing: View>: View {
@ViewBuilder let back: () -> Back
@ViewBuilder let title: () -> Title
@ViewBuilder let trailing: () -> Trailing

var body: some View {
HStack(spacing: 8) {
back()
.layoutPriority(MobileToolbarItemLayoutRole.fixedTrailingControls.swiftUILayoutPriority)
.fixedSize()
.mobileGlassCompactToolbarControl()

title()
.layoutPriority(MobileToolbarItemLayoutRole.compressibleTitle.swiftUILayoutPriority)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
.mobileGlassCompactToolbarControl()
.clipped()

trailing()
.layoutPriority(MobileToolbarItemLayoutRole.fixedTrailingControls.swiftUILayoutPriority)
.fixedSize()
.mobileGlassCompactToolbarControl()
}
.frame(maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .center)
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider renaming fixedTrailingControls for clarity.

The leading back() view is also assigned MobileToolbarItemLayoutRole.fixedTrailingControls (Line 12), even though it's a leading control. Functionally correct today (both leading and trailing controls just need "don't compress" priority), but the name will mislead future readers extending this enum with role-specific behavior beyond priority.

✏️ Optional rename
-    case fixedTrailingControls
+    case fixedControl

(and update all three call sites in this file plus WorkspaceTitleMenu.swift)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileWorkspacePriorityToolbar.swift`
around lines 4 - 29, The layout role name fixedTrailingControls is misleading
because MobileWorkspacePriorityToolbar uses it for both the leading back()
control and the trailing control, so rename the enum case to a more general
non-compressing/control-priority name and update the
MobileWorkspacePriorityToolbar body plus the matching usage in
WorkspaceTitleMenu.swift. Keep the behavior the same by preserving the current
swiftUILayoutPriority mapping, but make the symbol name reflect that it applies
to any fixed control, not just trailing ones.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift">

<violation number="1" location="Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift:3">
P3: `fixedTrailingControls` is currently applied to both the leading back control and trailing controls, so the name no longer reflects the role’s actual semantics. A position-agnostic name (for example, `fixedControl`) would make future role-specific behavior easier to reason about and reduce reader confusion.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

@@ -0,0 +1,13 @@
enum MobileToolbarItemLayoutRole {
case compressibleTitle
case fixedTrailingControls

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: fixedTrailingControls is currently applied to both the leading back control and trailing controls, so the name no longer reflects the role’s actual semantics. A position-agnostic name (for example, fixedControl) would make future role-specific behavior easier to reason about and reduce reader confusion.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift, line 3:

<comment>`fixedTrailingControls` is currently applied to both the leading back control and trailing controls, so the name no longer reflects the role’s actual semantics. A position-agnostic name (for example, `fixedControl`) would make future role-specific behavior easier to reason about and reduce reader confusion.</comment>

<file context>
@@ -0,0 +1,13 @@
+enum MobileToolbarItemLayoutRole {
+    case compressibleTitle
+    case fixedTrailingControls
+
+    var swiftUILayoutPriority: Double {
</file context>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift`:
- Around line 92-127: The delayed-terminal preview helper and capability
constant are duplicated here and in WorkspaceDetailDelayedTerminalPreviewView,
so consolidate them into one shared internal helper. Move the common
MobileWorkspaceActionCapabilities and MobileWorkspacePreview construction logic
into a single reusable function/symbol and have both preview views call it,
keeping only any screen-specific differences outside the shared path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 42981e21-f214-421e-81f4-c49f870266fa

📥 Commits

Reviewing files that changed from the base of the PR and between 023697d and acd8f83.

📒 Files selected for processing (2)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailDelayedTerminalPreviewView.swift

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift">

<violation number="1" location="Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileToolbarItemLayoutRole.swift:3">
P3: `fixedTrailingControls` is currently applied to both the leading back control and trailing controls, so the name no longer reflects the role’s actual semantics. A position-agnostic name (for example, `fixedControl`) would make future role-specific behavior easier to reason about and reduce reader confusion.</violation>
</file>

<file name="Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift">

<violation number="1" location="Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceDetailCreateDelayedTerminalPreviewView.swift:92">
P3: This introduces a second, parallel preview-workspace builder with its own action-capabilities constant in a sibling delayed-terminal preview file. Keeping these construction paths duplicated makes preview defaults easier to drift over time; consolidating them behind one shared internal helper would reduce maintenance risk.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ios/cmuxUITests/cmuxUITests.swift (1)

2399-2434: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider consolidating the duplicated polling scaffolding.

waitForCompactToolbarTitleHeightToFitControls and assertToolbarTitleYieldsToTrailingControls both hand-roll the same deadline/RunLoop.current.run polling loop pattern (capture frames, check a geometry predicate, sleep 0.05s, repeat until deadline, then fail with a formatted message). Since both were introduced/expanded in this same diff, extracting a small generic pollUntil(timeout:predicate:onTimeout:) helper would avoid the two implementations drifting independently as the toolbar geometry checks evolve.

Also applies to: 2544-2587

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/cmuxUITests/cmuxUITests.swift` around lines 2399 - 2434, The polling loop
logic is duplicated between waitForCompactToolbarTitleHeightToFitControls and
assertToolbarTitleYieldsToTrailingControls; extract the shared
deadline/RunLoop.current.run retry pattern into a small reusable helper such as
a generic pollUntil(timeout:predicate:onTimeout:) and have both methods delegate
to it. Keep the existing geometry-specific checks and XCTFail messages in the
callers, but remove the hand-rolled loop from each method so the toolbar
assertions stay consistent as they evolve.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@ios/cmuxUITests/cmuxUITests.swift`:
- Around line 2399-2434: The polling loop logic is duplicated between
waitForCompactToolbarTitleHeightToFitControls and
assertToolbarTitleYieldsToTrailingControls; extract the shared
deadline/RunLoop.current.run retry pattern into a small reusable helper such as
a generic pollUntil(timeout:predicate:onTimeout:) and have both methods delegate
to it. Keep the existing geometry-specific checks and XCTFail messages in the
callers, but remove the hand-rolled loop from each method so the toolbar
assertions stay consistent as they evolve.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 33b58e9f-5c8a-461a-844f-06c1676e0d55

📥 Commits

Reviewing files that changed from the base of the PR and between acd8f83 and 08a22ea.

📒 Files selected for processing (2)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/AgentChatDemoScreen.swift
  • ios/cmuxUITests/cmuxUITests.swift

@azooz2003-bit

Copy link
Copy Markdown
Collaborator Author

Artifact proof for final verification

Head verified: ad2ab57

Final verifier: APPROVED. The verifier inspected the current head, relevant Swift files, UI test assertions, screenshot evidence, focused result bundles, git diff --check, ./scripts/lint-ios-package-conventions.sh, and autoreview output.

Behavior proven:

  • The fixed/max-width title heuristic is removed.
  • WorkspaceDetailView and the inline agent-chat preview both use MobileWorkspacePriorityToolbar as one .principal toolbar item.
  • Back, title, and trailing controls are SwiftUI siblings in the same layout row.
  • Title priority is lower (-1), trailing/back controls are higher (1) and fixed-size.
  • Long titles truncate before the chat toggle and terminal picker.

Focused evidence:

  • Production toolbar UI tests passed: /tmp/cmux-ios-tprio-prodtoolbar/Logs/Test/Test-cmux-ios-2026.07.02_22-44-23--0700.xcresult
  • Inline preview UI tests passed: /tmp/cmux-ios-tprio-inline/Logs/Test/Test-cmux-ios-2026.07.02_22-50-59--0700.xcresult
  • Screenshot proof: /tmp/cmux-tprio-evidence/workspace-detail-production-priority-toolbar-ad2ab57.png
  • Isolated simulator: cmux-tprio-verify, UDID 5AD831AA-8F8C-42F6-BA3E-DA9A0D971C26
  • Local package convention lint: pass
  • Autoreview and cmux policy: pass
  • GitHub package-conventions-lint: pass

Tagged dogfood builds from this head:

  • macOS: tprio, http://127.0.0.1:17320/tprio
  • iOS simulator bundle: dev.cmux.ios.tprio

Residual risk: broad suites were still pending when this proof was added. Focused UI coverage and the final verifier approval cover the toolbar priority regression specifically.

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — ad2ab576 Deployed Jul 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants