Skip to content

Move sidebar appearance support out of ContentView - #3106

Closed
lawrencecchen wants to merge 1 commit into
mainfrom
refactor-sidebar-appearance-support
Closed

lawrencecchen wants to merge 1 commit into
mainfrom
refactor-sidebar-appearance-support

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Apr 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary\n- move sidebar background/material/preset support from ContentView into SidebarAppearanceSupport\n- keep behavior unchanged and avoid project-file churn by using the existing sidebar support source\n\n## Verification\n- ./scripts/reload.sh --tag sbarapp


Summary by cubic

Moved sidebar appearance logic out of ContentView into SidebarAppearanceSupport to isolate sidebar UI and simplify ContentView. No UI or behavior changes.

  • Refactors
    • Extracted sidebar background, materials, presets, border, and helpers (e.g., SidebarBackdrop, SidebarTrailingBorder, SidebarVisualEffectBackground, related enums) into Sources/Sidebar/SidebarAppearanceSupport.swift.
    • Preserved existing storage keys and behavior to avoid churn and keep the app unchanged.

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

Summary by CodeRabbit

  • Refactor
    • Reorganized sidebar appearance rendering components (glass effects, borders, backgrounds, and tint configuration) into a dedicated support module for improved code organization.

@vercel

vercel Bot commented Apr 22, 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 Apr 22, 2026 11:59am

@coderabbitai

coderabbitai Bot commented Apr 22, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Sidebar appearance rendering components—including background, border, glass effect, and tint configuration types—are relocated from ContentView.swift to a new dedicated file SidebarAppearanceSupport.swift. The functionality remains unchanged; this is a structural reorganization of existing sidebar UI code.

Changes

Cohort / File(s) Summary
Sidebar Appearance Refactoring
Sources/ContentView.swift
Removed 443 lines containing sidebar background rendering components (SidebarVisualEffectBackground, SidebarTrailingBorder, SidebarTerminalBackgroundView, SidebarBackdrop), configuration enums (SidebarMaterialOption, SidebarBlendModeOption, SidebarStateOption, SidebarPresetOption), constants (SidebarTintDefaults), and NSColor.hexString(includeAlpha:) extension.
Sidebar Appearance Implementation
Sources/Sidebar/SidebarAppearanceSupport.swift
Added 442 lines with all sidebar background rendering components, configuration types, and utility methods previously in ContentView.swift, now consolidated in a dedicated appearance support file.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Sidebar code hops to a new home,
No logic changed, just better roamed,
Appearance tucked where it belongs,
Organization sings its songs! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main refactoring: moving sidebar appearance support from ContentView to a separate file, which is the primary change in the 443-line migration.
Description check ✅ Passed The description covers what changed and why, includes verification steps, and is supplemented by cubic's auto-generated summary. However, it lacks testing details, demo video, and checklist items required by the template.
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.

✏️ 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 refactor-sidebar-appearance-support

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.

@greptile-apps

greptile-apps Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR is a pure file-organization refactoring: all sidebar appearance types (SidebarVisualEffectBackground, SidebarTrailingBorder, SidebarTerminalBackgroundView, SidebarBackdrop, SidebarMaterialOption, SidebarBlendModeOption, SidebarStateOption, SidebarTintDefaults, SidebarPresetOption, and NSColor.hexString) are moved verbatim from ContentView.swift into Sources/Sidebar/SidebarAppearanceSupport.swift. The only intentional access-level change is that SidebarTrailingBorder and SidebarBackdrop go from private to internal so they remain reachable from ContentView.swift across the file boundary.

Confidence Score: 5/5

Safe to merge — pure file-organization refactoring with no behavioral changes.

All moved code is byte-for-byte identical in logic; access-level adjustments are intentional and correct; no callers are broken; no new bugs introduced.

No files require special attention.

Important Files Changed

Filename Overview
Sources/ContentView.swift Removed ~450 lines of sidebar appearance code (structs and enums); call sites for SidebarBackdrop and SidebarTrailingBorder remain and correctly resolve to the new location.
Sources/Sidebar/SidebarAppearanceSupport.swift Received all moved sidebar appearance types; SidebarTrailingBorder and SidebarBackdrop correctly widened from private to internal for cross-file visibility; logic is identical to what was removed from ContentView.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CV[ContentView.swift]
    CA[cmuxApp.swift]
    KS[KeyboardShortcutSettingsFileStore.swift]
    WC[WorkspaceContentView.swift]

    CV -->|uses| SB[SidebarBackdrop]
    CV -->|uses| STB[SidebarTrailingBorder]
    CV -->|uses| SBMO[SidebarBlendModeOption]

    CA -->|uses| SMP[SidebarMaterialOption]
    CA -->|uses| SBMO
    CA -->|uses| SSO[SidebarStateOption]
    CA -->|uses| SPO[SidebarPresetOption]
    CA -->|uses| STD[SidebarTintDefaults]

    KS -->|uses| STD
    WC -->|uses| HEX["NSColor.hexString()"]

    subgraph SA["SidebarAppearanceSupport.swift - after PR"]
        SB
        STB
        SMP
        SBMO
        SSO
        SPO
        STD
        HEX
        SVEB["SidebarVisualEffectBackground - private"]
        STBV["SidebarTerminalBackgroundView - private"]
        SB --> SVEB
        SB --> STBV
    end
Loading

Reviews (1): Last reviewed commit: "refactor: move sidebar appearance suppor..." | Re-trigger Greptile

@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.

🧹 Nitpick comments (1)
Sources/Sidebar/SidebarAppearanceSupport.swift (1)

423-441: terminalBackgroundColor is written but never read.

The @State at Line 423 is only assigned in the onReceive handler at Lines 438–440 and never consumed in the view body — SidebarTerminalBackgroundView reads GhosttyApp.shared.defaultBackgroundColor directly at Line 434. The write still triggers a re-render that picks up the fresh shared value, so behavior is correct, but the state variable is effectively a dummy re-render signal and is easy to misread as the real source.

Behavior-preserving move, so non-blocking — consider threading the state into the background color (or replacing it with a bump counter) in a follow-up for clarity.

♻️ Suggested cleanup
-    `@State` private var terminalBackgroundColor: NSColor = GhosttyBackgroundTheme.currentColor()
+    `@State` private var terminalBackgroundColor: NSColor = GhosttyBackgroundTheme.currentColor()
@@
-            let alpha = CGFloat(GhosttyApp.shared.defaultBackgroundOpacity)
+            let alpha = CGFloat(GhosttyApp.shared.defaultBackgroundOpacity)
             return AnyView(
                 SidebarTerminalBackgroundView(
-                    backgroundColor: GhosttyApp.shared.defaultBackgroundColor,
+                    backgroundColor: terminalBackgroundColor,
                     opacity: alpha
                 )
                 .clipShape(RoundedRectangle(cornerRadius: cornerRadius, style: .continuous))
                 .onReceive(NotificationCenter.default.publisher(for: .ghosttyDefaultBackgroundDidChange)) { _ in
                     terminalBackgroundColor = GhosttyBackgroundTheme.currentColor()
                 }
             )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Sidebar/SidebarAppearanceSupport.swift` around lines 423 - 441, The
`@State` terminalBackgroundColor is only written in the onReceive handler and
never read, making it a dummy re-render signal; fix by either (A) thread the
state into the view by replacing GhosttyApp.shared.defaultBackgroundColor with
terminalBackgroundColor in the SidebarTerminalBackgroundView initializer and set
terminalBackgroundColor = GhosttyBackgroundTheme.currentColor() in the
onReceive, or (B) replace terminalBackgroundColor with a clearer bump counter
(e.g., backgroundChangeCounter) that you increment in onReceive and keep using
GhosttyApp.shared.defaultBackgroundColor, so the intent is explicit; update
references to terminalBackgroundColor, the onReceive closure, and
SidebarTerminalBackgroundView usage accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Sources/Sidebar/SidebarAppearanceSupport.swift`:
- Around line 423-441: The `@State` terminalBackgroundColor is only written in the
onReceive handler and never read, making it a dummy re-render signal; fix by
either (A) thread the state into the view by replacing
GhosttyApp.shared.defaultBackgroundColor with terminalBackgroundColor in the
SidebarTerminalBackgroundView initializer and set terminalBackgroundColor =
GhosttyBackgroundTheme.currentColor() in the onReceive, or (B) replace
terminalBackgroundColor with a clearer bump counter (e.g.,
backgroundChangeCounter) that you increment in onReceive and keep using
GhosttyApp.shared.defaultBackgroundColor, so the intent is explicit; update
references to terminalBackgroundColor, the onReceive closure, and
SidebarTerminalBackgroundView usage accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2627b32a-7c62-4704-86f3-800ff43f7bbf

📥 Commits

Reviewing files that changed from the base of the PR and between fdaf873 and c437f06.

📒 Files selected for processing (2)
  • Sources/ContentView.swift
  • Sources/Sidebar/SidebarAppearanceSupport.swift
💤 Files with no reviewable changes (1)
  • Sources/ContentView.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.

2 issues found across 2 files

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="Sources/Sidebar/SidebarAppearanceSupport.swift">

<violation number="1" location="Sources/Sidebar/SidebarAppearanceSupport.swift:374">
P1: Avoid calling `getRed` on the original NSColor if sRGB conversion fails, as this will crash if the color is not RGB-compatible.

(Based on your team's feedback about using safe fallbacks when NSColor conversion fails.) [FEEDBACK_USED]</violation>

<violation number="2" location="Sources/Sidebar/SidebarAppearanceSupport.swift:697">
P1: Return a safe fallback string instead of calling `getRed` on the original color if sRGB conversion fails.

(Based on your team's feedback about using safe fallbacks when NSColor conversion fails.) [FEEDBACK_USED]</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.


extension NSColor {
func hexString(includeAlpha: Bool = false) -> String {
let color = usingColorSpace(.sRGB) ?? self

@cubic-dev-ai cubic-dev-ai Bot Apr 22, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Return a safe fallback string instead of calling getRed on the original color if sRGB conversion fails.

(Based on your team's feedback about using safe fallbacks when NSColor conversion fails.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Sources/Sidebar/SidebarAppearanceSupport.swift, line 697:

<comment>Return a safe fallback string instead of calling `getRed` on the original color if sRGB conversion fails.

(Based on your team's feedback about using safe fallbacks when NSColor conversion fails.) </comment>

<file context>
@@ -268,3 +268,445 @@ func sidebarWorkspaceRowBackgroundStyle(
+
+extension NSColor {
+    func hexString(includeAlpha: Bool = false) -> String {
+        let color = usingColorSpace(.sRGB) ?? self
+        var red: CGFloat = 0
+        var green: CGFloat = 0
</file context>
Suggested change
let color = usingColorSpace(.sRGB) ?? self
guard let color = usingColorSpace(.sRGB) else { return includeAlpha ? "#00000000" : "#000000" }
Fix with Cubic

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.

Verified. This code was moved unchanged in this refactor, so I am keeping this PR behavior-preserving. The safe fallback change is valid follow-up work for a separate behavior-fix PR.

— Claude Code

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

/// Replicates bonsplit TabBarColors.nsColorSeparator derivation from chrome background.
private static func chromeSeparatorColor() -> NSColor {
let chrome = GhosttyBackgroundTheme.currentColor()
let srgb = chrome.usingColorSpace(.sRGB) ?? chrome

@cubic-dev-ai cubic-dev-ai Bot Apr 22, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: Avoid calling getRed on the original NSColor if sRGB conversion fails, as this will crash if the color is not RGB-compatible.

(Based on your team's feedback about using safe fallbacks when NSColor conversion fails.)

View Feedback

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At Sources/Sidebar/SidebarAppearanceSupport.swift, line 374:

<comment>Avoid calling `getRed` on the original NSColor if sRGB conversion fails, as this will crash if the color is not RGB-compatible.

(Based on your team's feedback about using safe fallbacks when NSColor conversion fails.) </comment>

<file context>
@@ -268,3 +268,445 @@ func sidebarWorkspaceRowBackgroundStyle(
+    /// Replicates bonsplit TabBarColors.nsColorSeparator derivation from chrome background.
+    private static func chromeSeparatorColor() -> NSColor {
+        let chrome = GhosttyBackgroundTheme.currentColor()
+        let srgb = chrome.usingColorSpace(.sRGB) ?? chrome
+        var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
+        srgb.getRed(&r, green: &g, blue: &b, alpha: &a)
</file context>
Suggested change
let srgb = chrome.usingColorSpace(.sRGB) ?? chrome
guard let srgb = chrome.usingColorSpace(.sRGB) else { return NSColor(white: 0.5, alpha: 0.26) }
Fix with Cubic

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.

Verified. This is pre-existing behavior in moved code. I am leaving it unchanged here to keep the refactor move-only; the safe fallback belongs in a separate focused fix.

— Claude Code

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the feedback! I've saved this as a new learning to improve future reviews.

@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 — c437f06c Deployed Apr 22, 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.

2 participants