Files
PlantGuide/PlantGuide/Core/DesignSystem/DesignSystem.swift
Trey t be0d298d9f Add dark mode support and design system foundation
- Create DesignSystem with ColorTokens, AppearanceManager, spacing, and typography
- Add appearance picker in Settings (System/Light/Dark modes)
- Replace hardcoded colors with design tokens in MainTabView and Enums+UI
- Inject AppearanceManager via environment in PlantGuideApp
- Add FEATURE_ROADMAP.md documenting 8 planned features

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 14:17:56 -06:00

105 lines
3.0 KiB
Swift

import SwiftUI
/// PlantGuide Design System
/// Central namespace for all design tokens and styling constants.
enum DesignSystem {
// MARK: - Colors
/// Semantic color tokens - use these instead of hardcoded colors
typealias Colors = ColorTokens
// MARK: - Spacing
enum Spacing {
/// 4pt
static let xxs: CGFloat = 4
/// 8pt
static let xs: CGFloat = 8
/// 12pt
static let sm: CGFloat = 12
/// 16pt
static let md: CGFloat = 16
/// 20pt
static let lg: CGFloat = 20
/// 24pt
static let xl: CGFloat = 24
/// 32pt
static let xxl: CGFloat = 32
/// 48pt
static let xxxl: CGFloat = 48
}
// MARK: - Corner Radius
enum CornerRadius {
/// 4pt - subtle rounding
static let xs: CGFloat = 4
/// 8pt - small components
static let sm: CGFloat = 8
/// 12pt - cards, buttons
static let md: CGFloat = 12
/// 16pt - larger cards
static let lg: CGFloat = 16
/// 20pt - modals, sheets
static let xl: CGFloat = 20
}
// MARK: - Typography
enum Typography {
/// Large title - 34pt bold
static let largeTitle = Font.largeTitle.bold()
/// Title 1 - 28pt bold
static let title1 = Font.title.bold()
/// Title 2 - 22pt semibold
static let title2 = Font.title2.weight(.semibold)
/// Title 3 - 20pt semibold
static let title3 = Font.title3.weight(.semibold)
/// Headline - 17pt semibold
static let headline = Font.headline
/// Body - 17pt regular
static let body = Font.body
/// Callout - 16pt regular
static let callout = Font.callout
/// Subheadline - 15pt regular
static let subheadline = Font.subheadline
/// Footnote - 13pt regular
static let footnote = Font.footnote
/// Caption 1 - 12pt regular
static let caption1 = Font.caption
/// Caption 2 - 11pt regular
static let caption2 = Font.caption2
}
// MARK: - Shadows
enum Shadow {
static let sm = ShadowStyle(color: .black.opacity(0.08), radius: 4, x: 0, y: 2)
static let md = ShadowStyle(color: .black.opacity(0.12), radius: 8, x: 0, y: 4)
static let lg = ShadowStyle(color: .black.opacity(0.16), radius: 16, x: 0, y: 8)
}
// MARK: - Icon Sizes
enum IconSize {
/// 16pt
static let sm: CGFloat = 16
/// 20pt
static let md: CGFloat = 20
/// 24pt
static let lg: CGFloat = 24
/// 32pt
static let xl: CGFloat = 32
/// 48pt
static let xxl: CGFloat = 48
}
}
// MARK: - Shadow Style
struct ShadowStyle {
let color: Color
let radius: CGFloat
let x: CGFloat
let y: CGFloat
}
extension View {
func shadow(_ style: ShadowStyle) -> some View {
self.shadow(color: style.color, radius: style.radius, x: style.x, y: style.y)
}
}