Files
Sportstime/SportsTime/Core/Design/UIDesignStyle.swift
Trey t d34be05d61 feat(design): add Classic Animated home screen style
New design style combines the Classic layout with subtle animated
backgrounds featuring floating sports icons and route lines.
Animations are slow and unobtrusive to avoid distracting from content.

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

196 lines
7.4 KiB
Swift

//
// UIDesignStyle.swift
// SportsTime
//
// 22 distinctive aesthetic variants for the home screen.
//
import SwiftUI
/// Available UI design aesthetics for the home screen
enum UIDesignStyle: String, CaseIterable, Identifiable, Codable {
// Default
case classic = "Classic"
case classicAnimated = "Classic Animated"
// Original experimental aesthetics
case brutalist = "Brutalist"
case luxuryEditorial = "Luxury Editorial"
case retroFuturism = "Retro-Futurism"
case glassmorphism = "Glassmorphism"
case neoBrutalist = "Neo-Brutalist"
case organic = "Organic"
case maximalistChaos = "Maximalist"
case swissModernist = "Swiss Modern"
case playful = "Playful"
case artDeco = "Art Deco"
case darkIndustrial = "Industrial"
case softPastel = "Soft Pastel"
// Polished app-inspired aesthetics
case flighty = "Flighty"
case seatGeek = "SeatGeek"
case appleMaps = "Apple Maps"
case things3 = "Things 3"
case airbnb = "Airbnb"
case spotify = "Spotify"
case nikeRunClub = "Nike Run Club"
case fantastical = "Fantastical"
case strava = "Strava"
case carrotWeather = "Carrot Weather"
var id: String { rawValue }
var description: String {
switch self {
case .classic:
return "The original SportsTime design"
case .classicAnimated:
return "Classic with animated sports backgrounds"
case .brutalist:
return "Raw, unpolished anti-design rebellion"
case .luxuryEditorial:
return "Magazine-quality dramatic typography"
case .retroFuturism:
return "80s sci-fi meets modern sports tech"
case .glassmorphism:
return "Frosted glass, flowing ethereal shapes"
case .neoBrutalist:
return "Bold blocks, harsh shadows, high contrast"
case .organic:
return "Soft curves, earthy tones, breathing life"
case .maximalistChaos:
return "Dense, layered, gloriously overwhelming"
case .swissModernist:
return "Grid-obsessed clinical precision"
case .playful:
return "Bouncy, candy colors, pure delight"
case .artDeco:
return "1920s glamour with gold accents"
case .darkIndustrial:
return "Moody metallic dashboard aesthetic"
case .softPastel:
return "Light, airy, dreamy gradients"
case .flighty:
return "Aviation dashboard, data-rich elegance"
case .seatGeek:
return "Sports ticketing, vibrant modern cards"
case .appleMaps:
return "Native iOS, clean and familiar"
case .things3:
return "Ultra-clean, beautiful spacing"
case .airbnb:
return "Travel-focused, warm and inviting"
case .spotify:
return "Dark elegance, bold typography"
case .nikeRunClub:
return "Athletic stats, dynamic energy"
case .fantastical:
return "Calendar elegance, data-dense"
case .strava:
return "Athletic tracking, orange accent"
case .carrotWeather:
return "Bold personality, gradient skies"
}
}
var iconName: String {
switch self {
case .classic: return "star.fill"
case .classicAnimated: return "sparkles"
case .brutalist: return "hammer.fill"
case .luxuryEditorial: return "book.fill"
case .retroFuturism: return "tv.fill"
case .glassmorphism: return "drop.fill"
case .neoBrutalist: return "square.fill"
case .organic: return "leaf.fill"
case .maximalistChaos: return "sparkles"
case .swissModernist: return "grid"
case .playful: return "face.smiling.fill"
case .artDeco: return "diamond.fill"
case .darkIndustrial: return "gearshape.fill"
case .softPastel: return "cloud.fill"
case .flighty: return "airplane"
case .seatGeek: return "ticket.fill"
case .appleMaps: return "map.fill"
case .things3: return "checkmark.circle.fill"
case .airbnb: return "house.fill"
case .spotify: return "waveform"
case .nikeRunClub: return "figure.run"
case .fantastical: return "calendar"
case .strava: return "location.fill"
case .carrotWeather: return "sun.max.fill"
}
}
var accentColor: Color {
switch self {
case .classic: return Color(red: 1.0, green: 0.45, blue: 0.2) // Warm Orange
case .classicAnimated: return Color(red: 1.0, green: 0.45, blue: 0.2) // Warm Orange (same as Classic)
case .brutalist: return .red
case .luxuryEditorial: return Color(red: 0.85, green: 0.65, blue: 0.13) // Gold
case .retroFuturism: return Color(red: 0.0, green: 1.0, blue: 0.8) // Cyan
case .glassmorphism: return Color(red: 0.6, green: 0.4, blue: 1.0) // Purple
case .neoBrutalist: return Color(red: 1.0, green: 0.8, blue: 0.0) // Yellow
case .organic: return Color(red: 0.4, green: 0.7, blue: 0.4) // Green
case .maximalistChaos: return Color(red: 1.0, green: 0.2, blue: 0.6) // Magenta
case .swissModernist: return .red
case .playful: return Color(red: 1.0, green: 0.4, blue: 0.6) // Pink
case .artDeco: return Color(red: 0.85, green: 0.65, blue: 0.13) // Gold
case .darkIndustrial: return Color(red: 1.0, green: 0.5, blue: 0.0) // Orange
case .softPastel: return Color(red: 0.7, green: 0.8, blue: 1.0) // Soft blue
case .flighty: return Color(red: 0.2, green: 0.5, blue: 1.0) // Blue
case .seatGeek: return Color(red: 0.85, green: 0.15, blue: 0.5) // Magenta
case .appleMaps: return Color(red: 0.0, green: 0.48, blue: 1.0) // Apple Blue
case .things3: return Color(red: 0.35, green: 0.6, blue: 0.95) // Things Blue
case .airbnb: return Color(red: 1.0, green: 0.22, blue: 0.4) // Airbnb Red
case .spotify: return Color(red: 0.12, green: 0.84, blue: 0.38) // Spotify Green
case .nikeRunClub: return Color(red: 0.77, green: 1.0, blue: 0.0) // Nike Volt
case .fantastical: return Color(red: 0.92, green: 0.26, blue: 0.26) // Fantastical Red
case .strava: return Color(red: 0.99, green: 0.32, blue: 0.15) // Strava Orange
case .carrotWeather: return Color(red: 1.0, green: 0.45, blue: 0.2) // Carrot Orange
}
}
}
// MARK: - Design Style Manager
@Observable
final class DesignStyleManager {
static let shared = DesignStyleManager()
private let userDefaultsKey = "selectedUIDesignStyle"
private(set) var currentStyle: UIDesignStyle {
didSet {
UserDefaults.standard.set(currentStyle.rawValue, forKey: userDefaultsKey)
}
}
private init() {
if let savedValue = UserDefaults.standard.string(forKey: userDefaultsKey),
let style = UIDesignStyle(rawValue: savedValue) {
self.currentStyle = style
} else {
self.currentStyle = .classic // Default to original design
}
}
func setStyle(_ style: UIDesignStyle) {
currentStyle = style
}
}
// MARK: - Environment Key
private struct DesignStyleKey: EnvironmentKey {
static let defaultValue: UIDesignStyle = .classic
}
extension EnvironmentValues {
var designStyle: UIDesignStyle {
get { self[DesignStyleKey.self] }
set { self[DesignStyleKey.self] = newValue }
}
}