refactor(theme): CardsTheme forwarded auf ManaTheme.forest (v1.6.0)
`mana-swift-core` v1.6.0 liefert alle acht Web-Theme-Variants nativ. CardsTheme bleibt als duenner Alias bestehen — alle ~290 Call-Sites muessen nicht in einem Sprint umziehen, neue Call-Sites koennen direkt `ManaTheme.forest.<token>` oder `@Environment(\.manaTheme)` nutzen. Spart ~100 LOC lokales HSL-Apparat. forest-Werte sind jetzt single-source in `mana/packages/themes/src/variants/forest.css`. 43/43 Tests gruen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2194da5b2c
commit
57e472ff34
1 changed files with 24 additions and 107 deletions
|
|
@ -1,112 +1,29 @@
|
|||
import ManaTokens
|
||||
import SwiftUI
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit
|
||||
|
||||
private typealias PlatformColorType = UIColor
|
||||
#elseif canImport(AppKit)
|
||||
import AppKit
|
||||
|
||||
private typealias PlatformColorType = NSColor
|
||||
#endif
|
||||
|
||||
/// Forest-Theme aus `mana/packages/themes/src/variants/forest.css`.
|
||||
/// Lokal in cards-native nachgebaut, weil ManaTokens v1.0.0 nur den
|
||||
/// Default-Theme (mana-Variant) liefert.
|
||||
/// Cards-Theme — forwarded auf ``ManaTheme/forest`` aus
|
||||
/// `mana-swift-core` v1.6.0.
|
||||
///
|
||||
/// Migration auf einen Theme-Switch in ManaTokens ist Phase ε aus
|
||||
/// `mana/docs/MANA_SWIFT.md` — bis dahin lebt forest hier.
|
||||
/// Bis v1.5.x lebte hier ein 120-LOC-HSL-Apparat als lokaler Nachbau
|
||||
/// der `forest.css`-Variant. Mit v1.6.0 liefert ManaTokens alle acht
|
||||
/// Web-Theme-Variants nativ — `forest` ist eine davon.
|
||||
///
|
||||
/// `CardsTheme` bleibt als dünner Alias bestehen, damit die ~290
|
||||
/// Call-Sites in dieser App nicht in einem einzigen Sprint umziehen
|
||||
/// müssen. Neue Call-Sites bevorzugen direkt `ManaTheme.forest.<token>`
|
||||
/// (oder `@Environment(\.manaTheme)` falls die App irgendwann
|
||||
/// Theme-Switching bekommt).
|
||||
enum CardsTheme {
|
||||
/// Page-Hintergrund
|
||||
static let background = dynamic(light: HSL(0, 0, 100), dark: HSL(142, 30, 8))
|
||||
|
||||
/// Standard-Text
|
||||
static let foreground = dynamic(light: HSL(142, 30, 12), dark: HSL(142, 15, 95))
|
||||
|
||||
/// Card, Panel, Modal
|
||||
static let surface = dynamic(light: HSL(142, 25, 98), dark: HSL(142, 25, 12))
|
||||
|
||||
/// Hover-State auf Surface
|
||||
static let surfaceHover = dynamic(light: HSL(142, 20, 95), dark: HSL(142, 20, 16))
|
||||
|
||||
/// Disabled-Felder, Skeleton
|
||||
static let muted = dynamic(light: HSL(142, 15, 93), dark: HSL(142, 18, 18))
|
||||
|
||||
/// Sekundär-Text, Placeholder
|
||||
static let mutedForeground = dynamic(light: HSL(142, 10, 42), dark: HSL(142, 12, 65))
|
||||
|
||||
/// Rahmen, Trennlinien
|
||||
static let border = dynamic(light: HSL(142, 15, 88), dark: HSL(142, 18, 22))
|
||||
|
||||
/// Cards-Brand-Grün — Tiefgrün im Light, leuchtender im Dark
|
||||
static let primary = dynamic(light: HSL(142, 76, 28), dark: HSL(142, 71, 45))
|
||||
|
||||
/// Text auf Primary
|
||||
static let primaryForeground = dynamic(light: HSL(0, 0, 100), dark: HSL(142, 30, 8))
|
||||
|
||||
static let error = dynamic(light: HSL(0, 84, 60), dark: HSL(0, 63, 55))
|
||||
static let success = dynamic(light: HSL(142, 71, 45), dark: HSL(142, 71, 45))
|
||||
static let warning = dynamic(light: HSL(38, 92, 50), dark: HSL(48, 96, 53))
|
||||
|
||||
// MARK: - HSL Helper
|
||||
|
||||
/// Hue/Saturation/Lightness als Wert-Typ. HSL ist konkreter als ein
|
||||
/// 3-Tupel und macht die Call-Sites lesbar.
|
||||
struct HSL {
|
||||
let hue: Double
|
||||
let saturation: Double
|
||||
let lightness: Double
|
||||
|
||||
init(_ hue: Double, _ saturation: Double, _ lightness: Double) {
|
||||
self.hue = hue
|
||||
self.saturation = saturation
|
||||
self.lightness = lightness
|
||||
}
|
||||
}
|
||||
|
||||
private static func dynamic(light: HSL, dark: HSL) -> Color {
|
||||
let lightColor = fromHSL(light.hue, light.saturation, light.lightness)
|
||||
let darkColor = fromHSL(dark.hue, dark.saturation, dark.lightness)
|
||||
|
||||
#if canImport(UIKit)
|
||||
return Color(uiColor: UIColor { trait in
|
||||
trait.userInterfaceStyle == .dark ? darkColor : lightColor
|
||||
})
|
||||
#elseif canImport(AppKit)
|
||||
return Color(nsColor: NSColor(name: nil) { appearance in
|
||||
let isDark = appearance.bestMatch(from: [.darkAqua, .vibrantDark]) != nil
|
||||
return isDark ? darkColor : lightColor
|
||||
})
|
||||
#else
|
||||
return Color(red: 0, green: 0, blue: 0)
|
||||
#endif
|
||||
}
|
||||
|
||||
private static func fromHSL(_ hue: Double, _ saturation: Double, _ lightness: Double) -> PlatformColorType {
|
||||
let h = hue / 360
|
||||
let s = saturation / 100
|
||||
let l = lightness / 100
|
||||
|
||||
if s == 0 {
|
||||
return PlatformColorType(red: l, green: l, blue: l, alpha: 1)
|
||||
}
|
||||
|
||||
let q = l < 0.5 ? l * (1 + s) : l + s - l * s
|
||||
let p = 2 * l - q
|
||||
let r = hueToRGB(p, q, h + 1.0 / 3.0)
|
||||
let g = hueToRGB(p, q, h)
|
||||
let b = hueToRGB(p, q, h - 1.0 / 3.0)
|
||||
|
||||
return PlatformColorType(red: r, green: g, blue: b, alpha: 1)
|
||||
}
|
||||
|
||||
private static func hueToRGB(_ p: Double, _ q: Double, _ rawT: Double) -> Double {
|
||||
var t = rawT
|
||||
if t < 0 { t += 1 }
|
||||
if t > 1 { t -= 1 }
|
||||
if t < 1.0 / 6.0 { return p + (q - p) * 6 * t }
|
||||
if t < 1.0 / 2.0 { return q }
|
||||
if t < 2.0 / 3.0 { return p + (q - p) * (2.0 / 3.0 - t) * 6 }
|
||||
return p
|
||||
}
|
||||
static let background = ManaTheme.forest.background
|
||||
static let foreground = ManaTheme.forest.foreground
|
||||
static let surface = ManaTheme.forest.surface
|
||||
static let surfaceHover = ManaTheme.forest.surfaceHover
|
||||
static let muted = ManaTheme.forest.muted
|
||||
static let mutedForeground = ManaTheme.forest.mutedForeground
|
||||
static let border = ManaTheme.forest.border
|
||||
static let primary = ManaTheme.forest.primary
|
||||
static let primaryForeground = ManaTheme.forest.primaryForeground
|
||||
static let error = ManaTheme.forest.error
|
||||
static let success = ManaTheme.forest.success
|
||||
static let warning = ManaTheme.forest.warning
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue