Skip to content

Restore modern macOS Settings chrome (regression from #4975) - #5073

Closed
austinywang wants to merge 4 commits into
mainfrom
issue-5071-settings-chrome
Closed

austinywang wants to merge 4 commits into
mainfrom
issue-5071-settings-chrome

Conversation

@austinywang

@austinywang austinywang commented Jun 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

After the Settings rewrite in #4975, the Settings window rendered with the legacy macOS titled-window chrome instead of the modern macOS Settings chrome on macOS 14+/Tahoe. The rewrite switched the Settings scene from SwiftUI's Settings { } (which gets the modern unified-compact Settings chrome for free) to a generic Window(...) scene, which defaults to the legacy titled-window look. Neither the SwiftUI scene nor SettingsWindowPresenter.configure(window:) applied the chrome explicitly.

Fix — Path A (chosen over Path B)

Path A preserves the Window(...) scene and applies the chrome explicitly. I chose it over Path B (reverting to Settings { }) because the Window(...) form backs the existing multi-instance / window-ID deep-link hooks — openWindow(id: SettingsWindowPresenter.windowID) (Sources/cmuxApp.swift:251) and the windowIdentifier-based focus/reuse logic in SettingsWindowPresenter. The dedicated Settings { } scene lacks those openWindow(id:) hooks, so switching scenes would be a larger, riskier change. Path A is the smaller, safer fix.

Changes:

  • Sources/cmuxApp.swift — add .windowToolbarStyle(.unifiedCompact) to the Settings Window(...) scene.
  • Sources/App/SettingsWindowPresenter.swift — configure(window:) now applies .fullSizeContentView, titlebarAppearsTransparent = true, titleVisibility = .hidden, attaches a non-customizable NSToolbar with no baseline separator, and sets toolbarStyle = .unifiedCompact on the AppKit window.

Regression test

Two-commit structure so CI proves the test catches the bug:

  1. Failing test only (red): testConfigureWindowAppliesModernSettingsChrome in cmuxTests/SettingsWindowPresenterTests.swift drives configure(window:) and asserts toolbarStyle == .unifiedCompact, styleMask.contains(.fullSizeContentView), titlebarAppearsTransparent == true, and toolbar != nil.
  2. The fix (green).

Fixes #5071.

🤖 Generated with Claude Code


Note

Low Risk
UI-only window chrome and test harness changes; existing Settings window ID, focus, and parenting behavior are unchanged.

Overview
Restores modern macOS Settings window chrome after the Settings scene moved from SwiftUI Settings { } to a generic Window(...), which regressed to legacy titled-window styling.

SettingsWindowPresenter.configure(window:) now calls applyModernSettingsChrome, setting full-size content view, transparent/hidden titlebar, a fixed non-customizable NSToolbar, unified compact toolbar style, and no titlebar separator. The Settings Window scene in cmuxApp also applies .windowToolbarStyle(.unifiedCompact) so SwiftUI and AppKit stay aligned.

Tests in SettingsWindowPresenterTests migrate from XCTest to Swift Testing (serialized suite for shared static state) and add coverage that configuration applies the modern chrome flags.

Reviewed by Cursor Bugbot for commit 152c881. Bugbot is set up for automated code reviews on this repo. Configure here.


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

Summary by CodeRabbit

  • New Features

    • Settings window now uses a modern macOS appearance: transparent titlebar, hidden title, full‑size content view, no titlebar separator, and unified compact toolbar styling for a more native, streamlined experience.
  • Tests

    • Test suite migrated to the new testing framework, serialized to avoid concurrent state issues, and updated/expanded to cover window styling, focus/parenting behavior, and size/clamping scenarios.

Asserts that SettingsWindowPresenter.configure(window:) applies the modern
macOS Settings chrome (unified compact toolbar, full-size content view,
transparent titlebar, attached NSToolbar). Fails on main because the chrome
is never applied after the #4975 Settings rewrite switched from the SwiftUI
Settings { } scene to a generic Window(...) scene.

Regression from #4975.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 1, 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 Jun 1, 2026 3:20am
cmux-staging Building Building Preview, Comment Jun 1, 2026 3:20am

@coderabbitai

coderabbitai Bot commented Jun 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f70d4273-4a69-4670-8efc-4f87e774fbac

📥 Commits

Reviewing files that changed from the base of the PR and between efa7b82 and 152c881.

📒 Files selected for processing (1)
  • cmuxTests/SettingsWindowPresenterTests.swift

📝 Walkthrough

Walkthrough

The PR applies modern macOS Settings window chrome (unified compact toolbar, transparent titlebar, full-size content view). A new presenter helper configures AppKit window properties; the presenter invokes it during setup and the SwiftUI scene sets the toolbar style modifier.

Changes

Settings window modern chrome

Layer / File(s) Summary
Settings chrome helper implementation
Sources/App/SettingsWindowPresenter.swift
New applyModernSettingsChrome(_:) private helper applies .fullSizeContentView style mask, transparent titlebar with hidden title visibility, ensures a non-customizable toolbar exists (creating one if needed), sets toolbarStyle = .unifiedCompact, and sets titlebarSeparatorStyle = .none. Includes toolbarIdentifier constant.
Chrome application in presenter and scene
Sources/App/SettingsWindowPresenter.swift, Sources/cmuxApp.swift
SettingsWindowPresenter.configure(window:) now calls applyModernSettingsChrome(window) after setting minSize and contentMinSize. The SwiftUI Settings window scene adds .windowToolbarStyle(.unifiedCompact).
Test suite migration and chrome verification
cmuxTests/SettingsWindowPresenterTests.swift
Tests migrated from XCTest to Swift Testing; suite marked serialized and updated tests assert modern chrome properties and related presenter behaviors (navigation consumption, refocus, miniaturize handling, reparenting, detachment on close, and clamping oversized frames).

Sequence Diagram:

sequenceDiagram
  participant Scene as SwiftUI Scene
  participant Presenter as SettingsWindowPresenter
  participant Window as NSWindow
  participant Toolbar as NSToolbar

  Scene->>Presenter: provide NSWindow
  Presenter->>Window: applyModernSettingsChrome(window)
  Presenter->>Toolbar: ensure toolbar exists
  Presenter->>Window: set toolbarStyle and separator
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs:

  • manaflow-ai/cmux#4661: Modifies SettingsWindowPresenter.configure(window:) with overlapping tests and focus/refocus behavior relevant to presenter lifecycle.

"🐰 I hopped in with a tiny fix,
hid titles, stitched a compact mix,
toolbar neat and borders gone,
Settings shine from dusk to dawn. ✨"

🚥 Pre-merge checks | ✅ 17 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (17 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change—restoring modern macOS Settings chrome—and directly references the regression issue (#4975), providing specific context for reviewers.
Description check ✅ Passed The description covers the summary, testing approach, and verification via a regression test. The two-commit structure (failing test, then fix) is explained; however, demo video and checklist items are missing.
Linked Issues check ✅ Passed The PR fully implements the recommended Path A approach from #5071: adds .windowToolbarStyle(.unifiedCompact) to the Settings Window scene, applies modern chrome flags in configure(window:) including full-size content view, transparent titlebar, and unified compact toolbar, and includes the regression test asserting these properties.
Out of Scope Changes check ✅ Passed All changes directly address #5071's restoration of modern Settings chrome. The test framework migration to Swift Testing is necessary to support the serialized test suite required for the new regression test.
Cmux Swift Actor Isolation ✅ Passed Production changes only add a private MainActor method and constant to configure modern Settings chrome; no new actor isolation mistakes introduced. Test changes excluded.
Cmux Swift Blocking Runtime ✅ Passed PR introduces no blocking/timing synchronization: only AppKit window configuration calls and SwiftUI styling, no Task.sleep/semaphores/locks/asyncAfter in production code.
Cmux No Hacky Sleeps ✅ Passed All PR changes are in Swift files (out of scope per rule). Rule covers only TypeScript, JavaScript, shell, and non-Swift build scripts. Swift timing covered by separate check.
Cmux Algorithmic Complexity ✅ Passed New applyModernSettingsChrome() performs only constant-time property assignments on a single window; no scalable-collection scans, nested loops, or hot-path inefficiencies.
Cmux Swift Concurrency ✅ Passed The PR adds only synchronous AppKit window configuration in the new applyModernSettingsChrome function with no legacy async patterns detected.
Cmux Swift @Concurrent ✅ Passed Changes comply with concurrent annotation rules: no invalid @concurrent usage, proper MainActor isolation, and UI-bound async work correctly annotated.
Cmux Swift File And Package Boundaries ✅ Passed Adds ~18 lines of UI chrome config to SettingsWindowPresenter (299 lines total, under threshold) and 1 line to cmuxApp. Pure AppKit window setup, no mixed responsibilities, complies with review rules.
Cmux Swift Logging ✅ Passed No logging violations detected. Production changes consist only of AppKit property assignments and SwiftUI modifiers with no print, NSLog, debugPrint, dump, or ad hoc logging.
Cmux User-Facing Error Privacy ✅ Passed PR contains only technical UI configuration (window appearance, SwiftUI modifiers, tests) with no user-facing errors or sensitive data exposure.
Cmux Full Internationalization ✅ Passed PR adds internal window configuration code and uses existing localized strings (settings.title) already fully translated. No new user-facing text violations of full-internationalization.md found.
Cmux Swiftui State Layout ✅ Passed No new SwiftUI state patterns added. Changes add only view modifier and AppKit window properties via NSViewRepresentable bridge (allowed exception).
Cmux Architecture Rethink ✅ Passed Small correctness fix restoring modern macOS Settings chrome with clear owner (SettingsWindowPresenter.configure) and invariants; no timing, locks, observers, or architectural debt introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed Settings window already has stable cmux.settings identifier and is registered in cmuxAuxiliaryWindowIdentifiers; PR only applies additional styling to existing compliant window.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 issue-5071-settings-chrome

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 and usage tips.

The #4975 Settings rewrite switched the Settings scene from SwiftUI's
`Settings { }` (which gets the modern unified-compact Settings chrome for
free on macOS 14+) to a generic `Window(...)` scene, which defaults to the
legacy titled-window chrome.

Path A (chosen over Path B): keep the `Window(...)` scene so the existing
multi-instance / window-ID deep-link hooks (`openWindow(id: SettingsWindowPresenter.windowID)`)
keep working, and apply the chrome explicitly:

- Add `.windowToolbarStyle(.unifiedCompact)` to the SwiftUI Window scene.
- Extend `SettingsWindowPresenter.configure(window:)` to insert
  `.fullSizeContentView`, set `titlebarAppearsTransparent`/`titleVisibility`,
  attach an `NSToolbar`, and set `toolbarStyle = .unifiedCompact` on the
  AppKit window.

Fixes #5071.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@austinywang
austinywang force-pushed the issue-5071-settings-chrome branch from f61ae25 to ab023e7 Compare June 1, 2026 01:19

@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 3 files

Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Jun 1, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR restores the modern macOS Settings window chrome (unified compact toolbar, transparent/hidden titlebar, full-size content view, no titlebar separator) that was implicitly provided by the SwiftUI Settings { } scene before #4975 switched to a generic Window(...) scene, which defaults to legacy titled-window styling.

  • SettingsWindowPresenter.configure(window:) now calls applyModernSettingsChrome(_:), which explicitly sets the five AppKit window properties that Settings { } previously applied for free; the Window(...) scene in cmuxApp.swift also gains .windowToolbarStyle(.unifiedCompact) at the SwiftUI scene level.
  • Tests are migrated from XCTest to Swift Testing (#expect, @Suite(.serialized)) and a new configureWindowAppliesModernSettingsChrome test asserts all five chrome properties are applied after configure(window:).

Confidence Score: 5/5

Presentation-only chrome restoration with no impact on app state, data, or auth; all five AppKit properties are idempotently applied and fully covered by the new test.

The change is narrowly scoped to window chrome: five AppKit properties set idempotently in a private helper, a single SwiftUI scene modifier, and a test that asserts every property. No logic, state, or data flow is touched.

No files require special attention.

Important Files Changed

Filename Overview
Sources/App/SettingsWindowPresenter.swift Adds idempotent applyModernSettingsChrome(_:) called once per configure(window:) invocation; all five AppKit properties are safe to re-apply and the toolbar guard prevents duplicate creation.
Sources/cmuxApp.swift Single-line addition of .windowToolbarStyle(.unifiedCompact) to the Settings Window(...) scene; consistent with the AppKit-level toolbarStyle set in applyModernSettingsChrome.
cmuxTests/SettingsWindowPresenterTests.swift Clean migration from XCTest to Swift Testing; .serialized suite trait correctly serializes tests that mutate shared static state; new chrome test asserts all five applied properties.

Sequence Diagram

sequenceDiagram
    participant Scene as cmuxApp Window Scene
    participant WA as WindowAccessor
    participant SWP as SettingsWindowPresenter
    participant NSW as NSWindow

    Scene->>NSW: Create Window("Settings", id: "settings")
    Scene->>NSW: .windowToolbarStyle(.unifiedCompact)
    NSW-->>WA: window callback
    WA->>SWP: configure(window:)
    SWP->>NSW: applyModernSettingsChrome()
    Note over SWP,NSW: styleMask.insert(.fullSizeContentView)<br/>titlebarAppearsTransparent = true<br/>titleVisibility = .hidden<br/>NSToolbar (if window.toolbar == nil)<br/>toolbarStyle = .unifiedCompact<br/>titlebarSeparatorStyle = .none
    SWP->>NSW: clampToVisibleAreaIfNeeded()
    SWP->>NSW: attachToPreferredParent()
Loading

Reviews (3): Last reviewed commit: "Migrate SettingsWindowPresenterTests to ..." | Re-trigger Greptile

Comment on lines +259 to +265
if window.toolbar == nil {
let toolbar = NSToolbar(identifier: toolbarIdentifier)
toolbar.allowsUserCustomization = false
window.toolbar = toolbar
}
window.toolbarStyle = .unifiedCompact
}

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 On macOS 12+, NSWindow.titlebarSeparatorStyle is the authoritative control for the separator line drawn between the titlebar area and the scrolling content. toolbar.showsBaselineSeparator = false suppresses the toolbar's own baseline separator but does not affect the window-level separator that titlebarSeparatorStyle controls. Without setting .none here, the window may render a shadow/line under the toolbar when content scrolls beneath it, which the original Settings { } scene suppressed automatically. The test does not assert titlebarSeparatorStyle, so this would not be caught by CI.

Suggested change
if window.toolbar == nil {
let toolbar = NSToolbar(identifier: toolbarIdentifier)
toolbar.allowsUserCustomization = false
window.toolbar = toolbar
}
window.toolbarStyle = .unifiedCompact
}
if window.toolbar == nil {
let toolbar = NSToolbar(identifier: toolbarIdentifier)
toolbar.allowsUserCustomization = false
toolbar.showsBaselineSeparator = false
window.toolbar = toolbar
}
window.toolbarStyle = .unifiedCompact
window.titlebarSeparatorStyle = .none

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed — fixed. Added window.titlebarSeparatorStyle = .none (the non-deprecated, window-level control) instead of showsBaselineSeparator, and added a test assertion for it so CI covers the property. Pushed in efa7b82.

— Claude Code

Comment on lines +26 to +29
XCTAssertEqual(settingsWindow.toolbarStyle, .unifiedCompact)
XCTAssertTrue(settingsWindow.styleMask.contains(.fullSizeContentView))
XCTAssertTrue(settingsWindow.titlebarAppearsTransparent)
XCTAssertNotNil(settingsWindow.toolbar)

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 test validates four of the five properties set by applyModernSettingsChrome, but omits an assertion for titleVisibility == .hidden. Adding it closes the coverage gap and ensures that property stays wired up if applyModernSettingsChrome is refactored later.

Suggested change
XCTAssertEqual(settingsWindow.toolbarStyle, .unifiedCompact)
XCTAssertTrue(settingsWindow.styleMask.contains(.fullSizeContentView))
XCTAssertTrue(settingsWindow.titlebarAppearsTransparent)
XCTAssertNotNil(settingsWindow.toolbar)
XCTAssertEqual(settingsWindow.toolbarStyle, .unifiedCompact)
XCTAssertTrue(settingsWindow.styleMask.contains(.fullSizeContentView))
XCTAssertTrue(settingsWindow.titlebarAppearsTransparent)
XCTAssertEqual(settingsWindow.titleVisibility, .hidden)
XCTAssertNotNil(settingsWindow.toolbar)

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!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done — added XCTAssertEqual(settingsWindow.titleVisibility, .hidden) (and also titlebarSeparatorStyle == .none for the new property). Pushed in efa7b82.

— Claude Code

@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: 2

🤖 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 `@cmuxTests/SettingsWindowPresenterTests.swift`:
- Around line 18-30: This XCTest-based test must be converted to Swift Testing:
change import XCTest to import Testing, change final class
SettingsWindowPresenterTests: XCTestCase to be annotated `@Suite` `@MainActor` final
class SettingsWindowPresenterTests, rename func
testConfigureWindowAppliesModernSettingsChrome() to `@Test` func
configureWindowAppliesModernSettingsChrome(), replace assertions
(XCTAssertEqual/XCTAssertTrue/XCTAssertNotNil) with `#expect`(...) forms (e.g.
`#expect`(settingsWindow.toolbarStyle == .unifiedCompact),
`#expect`(settingsWindow.styleMask.contains(.fullSizeContentView)),
`#expect`(settingsWindow.titlebarAppearsTransparent),
`#expect`(settingsWindow.toolbar != nil)), and ensure test cleanup calls
SettingsWindowPresenter.resetForTests() via a defer in the test; keep use of
makeWindow(...) and SettingsWindowPresenter.configure(window:) and the defer
that orderOut(nil).

In `@Sources/App/SettingsWindowPresenter.swift`:
- Around line 259-263: The toolbar created in SettingsWindowPresenter.swift (the
NSToolbar instance constructed using toolbarIdentifier and assigned to
window.toolbar) is missing the no-baseline-separator setting; after creating the
toolbar in the block where you set window.toolbar = toolbar, set
toolbar.showsBaselineSeparator = false on that NSToolbar instance so the
Settings chrome matches the modern macOS appearance.
🪄 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: 1f890b2f-48cc-48cd-baa3-560e1ebbc299

📥 Commits

Reviewing files that changed from the base of the PR and between 9f35444 and ab023e7.

📒 Files selected for processing (3)
  • Sources/App/SettingsWindowPresenter.swift
  • Sources/cmuxApp.swift
  • cmuxTests/SettingsWindowPresenterTests.swift

Comment thread cmuxTests/SettingsWindowPresenterTests.swift Outdated
Comment thread Sources/App/SettingsWindowPresenter.swift
Address review feedback: NSToolbar.showsBaselineSeparator (deprecated in
macOS 15) does not control the window-level separator. Set
window.titlebarSeparatorStyle = .none — the authoritative, non-deprecated
API — so the titlebar stays seamless when content scrolls, matching the
old Settings { } scene. Extend the regression test to assert titleVisibility
and titlebarSeparatorStyle so both stay wired up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per the repo coding guidelines (Swift Testing for all new/touched unit
tests), convert the suite from XCTest to Swift Testing: import Testing,
@suite struct with @test methods, #expect/#require assertions. Add
.serialized because every test mutates SettingsWindowPresenter's shared
static state and resets it on exit, which Swift Testing's default parallel
execution would otherwise race. tearDown's resetForTests() is now a per-test
defer; the XCTSkip-on-no-screen guard becomes an early return.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@austinywang austinywang closed this Jun 1, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — 152c881a Deployed Jun 1, 2026 by vercel[bot]
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.

Settings window renders legacy chrome on macOS 14+/Tahoe (regression from #4975 Settings rewrite)

1 participant