186 lines
6.8 KiB
Swift
186 lines
6.8 KiB
Swift
//
|
|
// Theme.swift
|
|
// wake
|
|
//
|
|
// Created by fairclip on 2025/8/19.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
// MARK: - 主题色管理
|
|
struct Theme {
|
|
|
|
// MARK: - 主要颜色
|
|
struct Colors {
|
|
|
|
// MARK: - 品牌色
|
|
static let primary = Color(hex: "FFB645") // 主橙色
|
|
static let primaryLight = Color(hex: "FFF8DE") // 浅橙色
|
|
static let primaryDark = Color(hex: "E6A03D") // 深橙色
|
|
|
|
// MARK: - 辅助色
|
|
static let secondary = Color(hex: "6C7B7F") // 灰蓝色
|
|
static let accent = Color(hex: "FF6B6B") // 强调红色
|
|
|
|
// MARK: - 中性色
|
|
static let background = Color(hex: "F8F9FA") // 背景色
|
|
static let surface = Color.white // 表面色
|
|
static let surfaceSecondary = Color(hex: "F5F5F5") // 次级表面色
|
|
|
|
// MARK: - 文本色
|
|
static let textPrimary = Color.black // 主文本色
|
|
static let textSecondary = Color(hex: "6B7280") // 次级文本色
|
|
static let textTertiary = Color(hex: "9CA3AF") // 三级文本色
|
|
static let textInverse = Color.white // 反色文本
|
|
static let textMessage = Color(hex: "7B7B7B") // 注释颜色
|
|
static let textMessageMain = Color(hex: "000000") // 注释主要颜色
|
|
static let textWhite = Color(hex: "FFFFFF") // 白色
|
|
static let textWhiteSecondary = Color(hex: "FAFAFA") // 白色次级
|
|
|
|
// MARK: - 状态色
|
|
static let success = Color(hex: "10B981") // 成功色
|
|
static let warning = Color(hex: "F59E0B") // 警告色
|
|
static let error = Color(hex: "EF4444") // 错误色
|
|
static let info = Color(hex: "3B82F6") // 信息色
|
|
|
|
// MARK: - 边框色
|
|
static let border = Color(hex: "E5E7EB") // 边框色
|
|
static let borderLight = Color(hex: "F3F4F6") // 浅边框色
|
|
static let borderDark = Color(hex: "D1D5DB") // 深边框色
|
|
|
|
// MARK: - 订阅相关色
|
|
static let freeBackground = primaryLight // Free版背景
|
|
static let pioneerBackground = primary // Pioneer版背景
|
|
static let subscribeButton = primary // 订阅按钮色
|
|
}
|
|
|
|
// MARK: - 渐变色
|
|
struct Gradients {
|
|
static let primaryGradient = LinearGradient(
|
|
colors: [Colors.primary, Colors.primaryDark],
|
|
startPoint: .topLeading,
|
|
endPoint: .bottomTrailing
|
|
)
|
|
|
|
static let backgroundGradient = LinearGradient(
|
|
colors: [Colors.background, Colors.surface],
|
|
startPoint: .top,
|
|
endPoint: .bottom
|
|
)
|
|
|
|
static let accentGradient = LinearGradient(
|
|
colors: [Colors.accent, Color(hex: "FF8E8E")],
|
|
startPoint: .leading,
|
|
endPoint: .trailing
|
|
)
|
|
}
|
|
|
|
// MARK: - 阴影
|
|
struct Shadows {
|
|
static let small = Color.black.opacity(0.1)
|
|
static let medium = Color.black.opacity(0.15)
|
|
static let large = Color.black.opacity(0.2)
|
|
|
|
// 阴影配置
|
|
static let cardShadow = (color: small, radius: CGFloat(4), x: CGFloat(0), y: CGFloat(2))
|
|
static let buttonShadow = (color: medium, radius: CGFloat(6), x: CGFloat(0), y: CGFloat(3))
|
|
static let modalShadow = (color: large, radius: CGFloat(12), x: CGFloat(0), y: CGFloat(8))
|
|
}
|
|
|
|
// MARK: - 圆角
|
|
struct CornerRadius {
|
|
static let small: CGFloat = 8
|
|
static let medium: CGFloat = 12
|
|
static let large: CGFloat = 16
|
|
static let extraLarge: CGFloat = 20
|
|
static let round: CGFloat = 50
|
|
}
|
|
|
|
// MARK: - 间距
|
|
struct Spacing {
|
|
static let xs: CGFloat = 4
|
|
static let sm: CGFloat = 8
|
|
static let md: CGFloat = 12
|
|
static let lg: CGFloat = 16
|
|
static let xl: CGFloat = 20
|
|
static let xxl: CGFloat = 24
|
|
static let xxxl: CGFloat = 32
|
|
}
|
|
}
|
|
|
|
// MARK: - 便捷扩展
|
|
extension Color {
|
|
/// 主题色快捷访问
|
|
static var themePrimary: Color { Theme.Colors.primary }
|
|
static var themePrimaryLight: Color { Theme.Colors.primaryLight }
|
|
static var themeSecondary: Color { Theme.Colors.secondary }
|
|
static var themeAccent: Color { Theme.Colors.accent }
|
|
static var themeBackground: Color { Theme.Colors.background }
|
|
static var themeSurface: Color { Theme.Colors.surface }
|
|
static var themeTextPrimary: Color { Theme.Colors.textPrimary }
|
|
static var themeTextSecondary: Color { Theme.Colors.textSecondary }
|
|
static var themeTextMessage: Color { Theme.Colors.textMessage }
|
|
static var themeTextMessageMain: Color { Theme.Colors.textMessageMain }
|
|
static var themeTextWhite: Color { Theme.Colors.textWhite }
|
|
static var themeTextWhiteSecondary: Color { Theme.Colors.textWhiteSecondary }
|
|
}
|
|
|
|
// MARK: - 预览
|
|
#Preview("Theme Colors") {
|
|
ScrollView {
|
|
VStack(spacing: Theme.Spacing.lg) {
|
|
// 品牌色
|
|
ColorPreviewSection(title: "品牌色", colors: [
|
|
("Primary", Theme.Colors.primary),
|
|
("Primary Light", Theme.Colors.primaryLight),
|
|
("Primary Dark", Theme.Colors.primaryDark)
|
|
])
|
|
|
|
// 辅助色
|
|
ColorPreviewSection(title: "辅助色", colors: [
|
|
("Secondary", Theme.Colors.secondary),
|
|
("Accent", Theme.Colors.accent)
|
|
])
|
|
|
|
// 状态色
|
|
ColorPreviewSection(title: "状态色", colors: [
|
|
("Success", Theme.Colors.success),
|
|
("Warning", Theme.Colors.warning),
|
|
("Error", Theme.Colors.error),
|
|
("Info", Theme.Colors.info)
|
|
])
|
|
}
|
|
.padding()
|
|
}
|
|
.background(Theme.Colors.background)
|
|
}
|
|
|
|
// MARK: - 预览辅助组件
|
|
struct ColorPreviewSection: View {
|
|
let title: String
|
|
let colors: [(String, Color)]
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: Theme.Spacing.sm) {
|
|
Text(title)
|
|
.font(.headline)
|
|
.foregroundColor(Theme.Colors.textPrimary)
|
|
|
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: Theme.Spacing.sm) {
|
|
ForEach(colors, id: \.0) { name, color in
|
|
VStack(spacing: Theme.Spacing.xs) {
|
|
Rectangle()
|
|
.fill(color)
|
|
.frame(height: 60)
|
|
.cornerRadius(Theme.CornerRadius.small)
|
|
|
|
Text(name)
|
|
.font(.caption)
|
|
.foregroundColor(Theme.Colors.textSecondary)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|