From 3412ff7003c7ac7217f3a5428c8d9401a18673eb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 22 Dec 2025 19:55:17 +0100 Subject: [PATCH] style: add macos chat glass background --- .../Sources/ClawdisChatUI/ChatComposer.swift | 5 +- .../ClawdisChatUI/ChatMessageViews.swift | 8 +-- .../Sources/ClawdisChatUI/ChatTheme.swift | 58 +++++++++++++++---- .../Sources/ClawdisChatUI/ChatView.swift | 2 +- 4 files changed, 56 insertions(+), 17 deletions(-) diff --git a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift index bb43715eb..878718cfa 100644 --- a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift +++ b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatComposer.swift @@ -45,7 +45,10 @@ struct ClawdisChatComposer: View { .background( RoundedRectangle(cornerRadius: 18, style: .continuous) .fill(ClawdisChatTheme.composerBackground) - .shadow(color: .black.opacity(0.08), radius: 10, y: 4)) + .overlay( + RoundedRectangle(cornerRadius: 18, style: .continuous) + .strokeBorder(ClawdisChatTheme.composerBorder, lineWidth: 1)) + .shadow(color: .black.opacity(0.12), radius: 12, y: 6)) #if os(macOS) .onDrop(of: [.fileURL], isTargeted: nil) { providers in self.handleDrop(providers) diff --git a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatMessageViews.swift b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatMessageViews.swift index 371961451..a266e221b 100644 --- a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatMessageViews.swift +++ b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatMessageViews.swift @@ -238,7 +238,7 @@ private struct ChatMessageBody: View { if self.style == .onboarding { return ClawdisChatTheme.onboardingAssistantBorder } - return Color.black.opacity(0.08) + return Color.white.opacity(0.08) } private var bubbleBorderWidth: CGFloat { @@ -321,7 +321,7 @@ struct ChatTypingIndicatorBubble: View { .fill(ClawdisChatTheme.assistantBubble)) .overlay( RoundedRectangle(cornerRadius: 16, style: .continuous) - .strokeBorder(Color.black.opacity(0.08), lineWidth: 1)) + .strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) .frame(maxWidth: ChatUIConstants.bubbleMaxWidth, alignment: .leading) } } @@ -340,7 +340,7 @@ struct ChatStreamingAssistantBubble: View { .fill(ClawdisChatTheme.assistantBubble)) .overlay( RoundedRectangle(cornerRadius: 16, style: .continuous) - .strokeBorder(Color.black.opacity(0.08), lineWidth: 1)) + .strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) .frame(maxWidth: ChatUIConstants.bubbleMaxWidth, alignment: .leading) } } @@ -374,7 +374,7 @@ struct ChatPendingToolsBubble: View { .fill(ClawdisChatTheme.assistantBubble)) .overlay( RoundedRectangle(cornerRadius: 16, style: .continuous) - .strokeBorder(Color.black.opacity(0.08), lineWidth: 1)) + .strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) .frame(maxWidth: ChatUIConstants.bubbleMaxWidth, alignment: .leading) } } diff --git a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatTheme.swift b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatTheme.swift index e7d11c57a..109a84f5f 100644 --- a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatTheme.swift +++ b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatTheme.swift @@ -15,6 +15,40 @@ enum ClawdisChatTheme { #endif } + @ViewBuilder + static var background: some View { + #if os(macOS) + ZStack { + LinearGradient( + colors: [ + Color(nsColor: .windowBackgroundColor).opacity(0.85), + Color.black.opacity(0.92) + ], + startPoint: .topLeading, + endPoint: .bottomTrailing) + RadialGradient( + colors: [ + Color(nsColor: .systemOrange).opacity(0.18), + .clear + ], + center: .topLeading, + startRadius: 40, + endRadius: 320) + RadialGradient( + colors: [ + Color(nsColor: .systemTeal).opacity(0.16), + .clear + ], + center: .topTrailing, + startRadius: 40, + endRadius: 280) + Color.black.opacity(0.12) + } + #else + Color(uiColor: .systemBackground) + #endif + } + static var card: Color { #if os(macOS) Color(nsColor: .textBackgroundColor) @@ -23,11 +57,11 @@ enum ClawdisChatTheme { #endif } - static var subtleCard: Color { + static var subtleCard: AnyShapeStyle { #if os(macOS) - Color(nsColor: .textBackgroundColor).opacity(0.55) + AnyShapeStyle(.ultraThinMaterial) #else - Color(uiColor: .secondarySystemBackground).opacity(0.9) + AnyShapeStyle(Color(uiColor: .secondarySystemBackground).opacity(0.9)) #endif } @@ -41,7 +75,9 @@ enum ClawdisChatTheme { static var assistantBubble: Color { #if os(macOS) - Color(nsColor: .controlBackgroundColor) + let base = NSColor.controlBackgroundColor + let blended = base.blended(withFraction: 0.18, of: .white) ?? base + return Color(nsColor: blended).opacity(0.88) #else Color(uiColor: .secondarySystemBackground) #endif @@ -75,24 +111,24 @@ enum ClawdisChatTheme { #endif } - static var composerBackground: Color { + static var composerBackground: AnyShapeStyle { #if os(macOS) - Color(nsColor: .windowBackgroundColor) + AnyShapeStyle(.ultraThinMaterial) #else - Color(uiColor: .systemBackground) + AnyShapeStyle(Color(uiColor: .systemBackground)) #endif } - static var composerField: Color { + static var composerField: AnyShapeStyle { #if os(macOS) - Color(nsColor: .textBackgroundColor) + AnyShapeStyle(.thinMaterial) #else - Color(uiColor: .secondarySystemBackground) + AnyShapeStyle(Color(uiColor: .secondarySystemBackground)) #endif } static var composerBorder: Color { - Color.secondary.opacity(0.2) + Color.white.opacity(0.12) } static var divider: Color { diff --git a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatView.swift b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatView.swift index 6ed66da74..2a1e5894d 100644 --- a/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatView.swift +++ b/apps/shared/ClawdisKit/Sources/ClawdisChatUI/ChatView.swift @@ -44,7 +44,7 @@ public struct ClawdisChatView: View { public var body: some View { ZStack { - ClawdisChatTheme.surface + ClawdisChatTheme.background .ignoresSafeArea() VStack(spacing: Layout.stackSpacing) {