montana/Montana-iOS/Sources/MontanaApp/UI/Theme/ClaudeTheme.swift

110 lines
4.2 KiB
Swift

import SwiftUI
enum ClaudeTheme {
enum Palette {
static let canvas = Color(red: 0.965, green: 0.953, blue: 0.929)
static let surface = Color(red: 0.984, green: 0.976, blue: 0.957)
static let surfaceRaised = Color.white
static let border = Color(red: 0.890, green: 0.871, blue: 0.831)
static let divider = Color(red: 0.918, green: 0.902, blue: 0.867)
static let textPrimary = Color(red: 0.122, green: 0.118, blue: 0.110)
static let textSecondary = Color(red: 0.412, green: 0.392, blue: 0.357)
static let textTertiary = Color(red: 0.612, green: 0.588, blue: 0.541)
static let accent = Color(red: 0.851, green: 0.459, blue: 0.341)
static let accentSoft = Color(red: 0.961, green: 0.882, blue: 0.847)
static let success = Color(red: 0.380, green: 0.604, blue: 0.471)
static let danger = Color(red: 0.776, green: 0.286, blue: 0.286)
}
enum 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 = 24
static let xxl: CGFloat = 32
}
enum Radius {
static let sm: CGFloat = 8
static let md: CGFloat = 12
static let lg: CGFloat = 16
static let pill: CGFloat = 999
}
enum Typography {
static let display = Font.system(size: 28, weight: .semibold, design: .serif)
static let title = Font.system(size: 22, weight: .semibold, design: .serif)
static let headline = Font.system(size: 17, weight: .semibold, design: .default)
static let body = Font.system(size: 16, weight: .regular, design: .default)
static let callout = Font.system(size: 15, weight: .regular, design: .default)
static let caption = Font.system(size: 13, weight: .regular, design: .default)
static let mono = Font.system(size: 13, weight: .regular, design: .monospaced)
}
}
struct ClaudeBackground: ViewModifier {
func body(content: Content) -> some View {
content
.background(ClaudeTheme.Palette.canvas.ignoresSafeArea())
}
}
struct ClaudeCard: ViewModifier {
var padding: CGFloat = ClaudeTheme.Spacing.lg
func body(content: Content) -> some View {
content
.padding(padding)
.background(
RoundedRectangle(cornerRadius: ClaudeTheme.Radius.md, style: .continuous)
.fill(ClaudeTheme.Palette.surface)
)
.overlay(
RoundedRectangle(cornerRadius: ClaudeTheme.Radius.md, style: .continuous)
.strokeBorder(ClaudeTheme.Palette.border, lineWidth: 0.5)
)
}
}
struct ClaudePrimaryButton: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(ClaudeTheme.Typography.headline)
.foregroundStyle(Color.white)
.frame(maxWidth: .infinity)
.padding(.vertical, 14)
.background(
RoundedRectangle(cornerRadius: ClaudeTheme.Radius.md, style: .continuous)
.fill(ClaudeTheme.Palette.accent.opacity(configuration.isPressed ? 0.85 : 1))
)
}
}
struct ClaudeSecondaryButton: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(ClaudeTheme.Typography.headline)
.foregroundStyle(ClaudeTheme.Palette.textPrimary)
.frame(maxWidth: .infinity)
.padding(.vertical, 14)
.background(
RoundedRectangle(cornerRadius: ClaudeTheme.Radius.md, style: .continuous)
.fill(ClaudeTheme.Palette.surfaceRaised.opacity(configuration.isPressed ? 0.7 : 1))
)
.overlay(
RoundedRectangle(cornerRadius: ClaudeTheme.Radius.md, style: .continuous)
.strokeBorder(ClaudeTheme.Palette.border, lineWidth: 1)
)
}
}
extension View {
func claudeBackground() -> some View { modifier(ClaudeBackground()) }
func claudeCard(padding: CGFloat = ClaudeTheme.Spacing.lg) -> some View {
modifier(ClaudeCard(padding: padding))
}
}