Repository navigation
sidebar: organize and drag workspaces (reorder, groups, glass look) #18334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
711fa03
165c71a
c5936c3
48cdd75
a93b300
8bdb9f6
3429333
6d79325
fbbe32a
aa81c0a
410ca2f
5577cd0
24589aa
2f3fe09
c8d1e9a
aa23a95
f881849
027e247
8e02887
b8c8c0e
c9b3b66
8b472a7
7d33fe9
a4b2031
d8669e1
ddd1fed
8cdd197
5d33457
d1c8c1e
1a02517
ecb53be
d989744
02816ae
ae154a8
f0e8a9c
5194180
f853384
7533734
23a275d
b39bd88
076ae7f
3c783f9
77eab49
218d22a
fe96d1b
5fec384
c5a411f
d4196a4
004010c
df98f3e
150f830
ee1ca41
5b2c4c9
e821000
cbe6b50
e390ad9
2ed7d64
f781014
d17ffd0
f29a992
74175cd
0f1fa9b
0dd9382
69b4a75
de2277d
b7b23f9
0b09950
ed36bfd
dad39a8
8b24a2b
03af860
53d4ead
77b039f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,26 @@ public struct SidebarBackdropSettingsSnapshot { | |
| /// Color scheme used to pick light/dark tint overrides. | ||
| public let colorScheme: ColorScheme | ||
|
|
||
| /// Whether the sidebar glass is a clear window ground with a compositor | ||
| /// blur behind it (tint painted on top) instead of an AppKit material. | ||
| /// This is the only path with an adjustable blur radius. | ||
| public let compositorGlass: Bool | ||
|
|
||
| /// Compositor blur radius in points, used when `compositorGlass` is on. | ||
| /// Read through `effectiveCompositorBlurRadius`, which clamps it. | ||
| public let compositorBlurRadius: Double | ||
|
|
||
| /// Blur radius bounds in points. Mirrors the settings catalog's range | ||
| /// (this module cannot import it): a floor so the sidebar always reads | ||
| /// as glass, a ceiling before blur turns to smear. | ||
| public static let compositorBlurRadiusRange: ClosedRange<Double> = 12...60 | ||
|
|
||
| /// The blur radius the window actually receives, clamped to the range. | ||
| public var effectiveCompositorBlurRadius: Int { | ||
| let range = Self.compositorBlurRadiusRange | ||
| return Int(min(range.upperBound, max(range.lowerBound, compositorBlurRadius)).rounded()) | ||
| } | ||
|
|
||
| /// Creates a sidebar backdrop settings snapshot. | ||
| public init( | ||
| materialRawValue: String, | ||
|
|
@@ -45,7 +65,9 @@ public struct SidebarBackdropSettingsSnapshot { | |
| tintOpacity: Double, | ||
| cornerRadius: Double, | ||
| blurOpacity: Double, | ||
| colorScheme: ColorScheme | ||
| colorScheme: ColorScheme, | ||
| compositorGlass: Bool = false, | ||
| compositorBlurRadius: Double = Self.compositorBlurRadiusRange.lowerBound | ||
| ) { | ||
| self.materialRawValue = materialRawValue | ||
| self.blendModeRawValue = blendModeRawValue | ||
|
|
@@ -57,23 +79,34 @@ public struct SidebarBackdropSettingsSnapshot { | |
| self.cornerRadius = cornerRadius | ||
| self.blurOpacity = blurOpacity | ||
| self.colorScheme = colorScheme | ||
| self.compositorGlass = compositorGlass | ||
| self.compositorBlurRadius = compositorBlurRadius | ||
| } | ||
|
|
||
| /// Tint-only policy for the compositor-glass path: the window ground is | ||
| /// clear and the compositor blurs behind it, so the sidebar layer paints | ||
| /// just the tint. No effect view is created for a nil material. | ||
| /// | ||
| /// Chosen by `WindowAppearanceSnapshot`, which owns the decision, so the | ||
| /// layer can never go tint-only over a ground that stayed opaque. | ||
| public var tintOnlyMaterialPolicy: SidebarBackdropMaterialPolicy { | ||
| SidebarBackdropMaterialPolicy( | ||
| material: nil, | ||
| blendingMode: .behindWindow, | ||
| state: .active, | ||
| opacity: 1.0, | ||
| tintColor: resolvedTintColor, | ||
| cornerRadius: CGFloat(max(0, cornerRadius)), | ||
| preferLiquidGlass: false, | ||
| usesWindowLevelGlass: false | ||
| ) | ||
| } | ||
|
|
||
| /// Resolved AppKit material policy for these settings. | ||
| public var materialPolicy: SidebarBackdropMaterialPolicy { | ||
| let materialOption = WindowChromeSidebarMaterialOption(rawValue: materialRawValue) | ||
| let blendingMode = WindowChromeSidebarBlendModeOption(rawValue: blendModeRawValue)?.mode ?? .behindWindow | ||
| let state = WindowChromeSidebarStateOption(rawValue: stateRawValue)?.state ?? .active | ||
| let resolvedHex: String | ||
| if colorScheme == .dark, let tintHexDark { | ||
| resolvedHex = tintHexDark | ||
| } else if colorScheme == .light, let tintHexLight { | ||
| resolvedHex = tintHexLight | ||
| } else { | ||
| resolvedHex = tintHex | ||
| } | ||
| let tintColor = (NSColor(hex: resolvedHex) ?? NSColor(hex: tintHex) ?? .black) | ||
| .withAlphaComponent(tintOpacity) | ||
| let preferLiquidGlass = materialOption?.usesLiquidGlass ?? false | ||
| let usesWindowLevelGlass = preferLiquidGlass && blendingMode == .behindWindow | ||
|
|
||
|
|
@@ -82,13 +115,34 @@ public struct SidebarBackdropSettingsSnapshot { | |
| blendingMode: blendingMode, | ||
| state: state, | ||
| opacity: blurOpacity, | ||
| tintColor: tintColor, | ||
| tintColor: resolvedTintColor, | ||
| cornerRadius: CGFloat(max(0, cornerRadius)), | ||
| preferLiquidGlass: preferLiquidGlass, | ||
| usesWindowLevelGlass: usesWindowLevelGlass | ||
| ) | ||
| } | ||
|
|
||
| /// The tint colour with its opacity baked in, honouring the per-scheme | ||
| /// overrides. Light mode swaps the stock dark tint for the light default; | ||
| /// a chosen colour, or a chosen opacity, still wins. | ||
| var resolvedTintColor: NSColor { | ||
| var resolvedHex = tintHex | ||
| var opacity = tintOpacity | ||
| if colorScheme == .dark, let tintHexDark { | ||
| resolvedHex = tintHexDark | ||
| } else if colorScheme == .light, let tintHexLight { | ||
| resolvedHex = tintHexLight | ||
| } else if colorScheme == .light { | ||
| let stock = WindowChromeSidebarTintDefaults() | ||
| if tintHex.caseInsensitiveCompare(stock.hex) == .orderedSame { | ||
| resolvedHex = WindowChromeSidebarTintDefaults.light.hex | ||
| if tintOpacity == stock.opacity { opacity = WindowChromeSidebarTintDefaults.light.opacity } | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Light stock tint ignores empty overrideMedium Severity The new light-mode stock swap only runs when Reviewed by Cursor Bugbot for commit 77b039f. Configure here. |
||
| } | ||
| return (NSColor(hex: resolvedHex) ?? NSColor(hex: tintHex) ?? .black) | ||
| .withAlphaComponent(opacity) | ||
| } | ||
|
|
||
| /// Stable identity for AppKit mutations. | ||
| public var appKitMutationID: String { | ||
| [ | ||
|
|
@@ -102,6 +156,8 @@ public struct SidebarBackdropSettingsSnapshot { | |
| identityComponent(cornerRadius), | ||
| identityComponent(blurOpacity), | ||
| String(describing: colorScheme), | ||
| String(compositorGlass), | ||
| identityComponent(compositorBlurRadius), | ||
| ].joined(separator: "|") | ||
| } | ||
|
|
||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🔵 Trivial
Behavior change: confirm the new fresh-install defaults are intended.
The fallbacks change to HUD material, behind-window blend, active state,
bgGlassEnabled=true, andsidebarCompositorGlass=true. Users without stored keys see a visible look change. The PR notes already flag this for the Match Terminal Background default. Make sure the settings catalog defaults, theWindowBackgroundSettingsReadingdefaults, and these fallbacks stay in sync. Today they match.Also applies to: 91-91, 94-96
🤖 Prompt for AI Agents