- 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>
105 lines
3.0 KiB
Swift
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)
|
|
}
|
|
}
|