Files
openclaw/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTheme.swift

175 lines
4.7 KiB
Swift
Raw Normal View History

import SwiftUI
#if os(macOS)
import AppKit
#else
import UIKit
#endif
#if os(macOS)
extension NSAppearance {
fileprivate var isDarkAqua: Bool {
self.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
}
}
#endif
2026-01-30 03:15:10 +01:00
enum OpenClawChatTheme {
#if os(macOS)
static func resolvedAssistantBubbleColor(for appearance: NSAppearance) -> NSColor {
// NSColor semantic colors don't reliably resolve for arbitrary NSAppearance in SwiftPM.
// Use explicit light/dark values so the bubble updates when the system appearance flips.
appearance.isDarkAqua
? NSColor(calibratedWhite: 0.18, alpha: 0.88)
: NSColor(calibratedWhite: 0.94, alpha: 0.92)
}
static func resolvedOnboardingAssistantBubbleColor(for appearance: NSAppearance) -> NSColor {
appearance.isDarkAqua
? NSColor(calibratedWhite: 0.20, alpha: 0.94)
: NSColor(calibratedWhite: 0.97, alpha: 0.98)
}
static let assistantBubbleDynamicNSColor = NSColor(
2026-01-30 03:15:10 +01:00
name: NSColor.Name("OpenClawChatTheme.assistantBubble"),
dynamicProvider: resolvedAssistantBubbleColor(for:))
static let onboardingAssistantBubbleDynamicNSColor = NSColor(
2026-01-30 03:15:10 +01:00
name: NSColor.Name("OpenClawChatTheme.onboardingAssistantBubble"),
dynamicProvider: resolvedOnboardingAssistantBubbleColor(for:))
#endif
static var surface: Color {
#if os(macOS)
Color(nsColor: .windowBackgroundColor)
#else
Color(uiColor: .systemBackground)
#endif
}
2025-12-22 19:55:17 +01:00
@ViewBuilder
static var background: some View {
#if os(macOS)
ZStack {
2025-12-24 14:29:40 +01:00
Rectangle()
.fill(.ultraThinMaterial)
2025-12-22 19:55:17 +01:00
LinearGradient(
colors: [
2025-12-24 14:29:40 +01:00
Color.white.opacity(0.12),
Color(nsColor: .windowBackgroundColor).opacity(0.35),
Color.black.opacity(0.35),
2025-12-22 19:55:17 +01:00
],
startPoint: .topLeading,
endPoint: .bottomTrailing)
RadialGradient(
colors: [
2025-12-24 14:29:40 +01:00
Color(nsColor: .systemOrange).opacity(0.14),
2025-12-23 01:41:13 +01:00
.clear,
2025-12-22 19:55:17 +01:00
],
center: .topLeading,
startRadius: 40,
endRadius: 320)
RadialGradient(
colors: [
2025-12-24 14:29:40 +01:00
Color(nsColor: .systemTeal).opacity(0.12),
2025-12-23 01:41:13 +01:00
.clear,
2025-12-22 19:55:17 +01:00
],
center: .topTrailing,
startRadius: 40,
endRadius: 280)
2025-12-24 14:29:40 +01:00
Color.black.opacity(0.08)
2025-12-22 19:55:17 +01:00
}
#else
Color(uiColor: .systemBackground)
#endif
}
static var card: Color {
#if os(macOS)
Color(nsColor: .textBackgroundColor)
#else
Color(uiColor: .secondarySystemBackground)
#endif
}
2025-12-22 19:55:17 +01:00
static var subtleCard: AnyShapeStyle {
#if os(macOS)
2025-12-22 19:55:17 +01:00
AnyShapeStyle(.ultraThinMaterial)
#else
2025-12-22 19:55:17 +01:00
AnyShapeStyle(Color(uiColor: .secondarySystemBackground).opacity(0.9))
#endif
}
2025-12-20 16:51:39 +00:00
static var userBubble: Color {
2025-12-30 06:47:19 +01:00
Color(red: 127 / 255.0, green: 184 / 255.0, blue: 212 / 255.0)
2025-12-20 16:51:39 +00:00
}
static var assistantBubble: Color {
#if os(macOS)
Color(nsColor: self.assistantBubbleDynamicNSColor)
2025-12-20 16:51:39 +00:00
#else
Color(uiColor: .secondarySystemBackground)
#endif
}
static var onboardingAssistantBubble: Color {
#if os(macOS)
Color(nsColor: self.onboardingAssistantBubbleDynamicNSColor)
#else
Color(uiColor: .secondarySystemBackground)
2025-12-20 16:51:39 +00:00
#endif
}
static var onboardingAssistantBorder: Color {
#if os(macOS)
Color.white.opacity(0.12)
#else
Color.white.opacity(0.12)
#endif
}
2025-12-20 16:51:39 +00:00
static var userText: Color { .white }
static var assistantText: Color {
#if os(macOS)
Color(nsColor: .labelColor)
#else
Color(uiColor: .label)
#endif
}
2025-12-22 19:55:17 +01:00
static var composerBackground: AnyShapeStyle {
2025-12-20 16:51:39 +00:00
#if os(macOS)
2025-12-22 19:55:17 +01:00
AnyShapeStyle(.ultraThinMaterial)
2025-12-20 16:51:39 +00:00
#else
2025-12-22 19:55:17 +01:00
AnyShapeStyle(Color(uiColor: .systemBackground))
2025-12-20 16:51:39 +00:00
#endif
}
2025-12-22 19:55:17 +01:00
static var composerField: AnyShapeStyle {
2025-12-20 16:51:39 +00:00
#if os(macOS)
2025-12-22 19:55:17 +01:00
AnyShapeStyle(.thinMaterial)
2025-12-20 16:51:39 +00:00
#else
2025-12-22 19:55:17 +01:00
AnyShapeStyle(Color(uiColor: .secondarySystemBackground))
2025-12-20 16:51:39 +00:00
#endif
}
static var composerBorder: Color {
2025-12-22 19:55:17 +01:00
Color.white.opacity(0.12)
2025-12-20 16:51:39 +00:00
}
static var divider: Color {
Color.secondary.opacity(0.2)
}
}
2026-01-30 03:15:10 +01:00
enum OpenClawPlatformImageFactory {
static func image(_ image: OpenClawPlatformImage) -> Image {
#if os(macOS)
Image(nsImage: image)
#else
Image(uiImage: image)
#endif
}
}