Add dynamic text contrast for mood colors and make theme preview full screen
- Add WCAG-compliant luminance calculation to Color extension - Add contrastingTextColor method to MoodTints for automatic black/white text - Update 12+ entry styles to use dynamic text colors instead of hardcoded white - Change theme preview sheet to full screen presentation Text now automatically switches between black and white based on background brightness, fixing readability issues on light mood colors like yellow (Good). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,40 @@ extension String {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Luminance & Contrast
|
||||
|
||||
extension Color {
|
||||
/// Calculate relative luminance using WCAG formula
|
||||
/// Returns value between 0 (darkest) and 1 (lightest)
|
||||
var luminance: Double {
|
||||
guard let components = cgColor?.components, components.count >= 3 else {
|
||||
return 0.5 // Default to mid-gray if can't determine
|
||||
}
|
||||
|
||||
let r = components[0]
|
||||
let g = components[1]
|
||||
let b = components[2]
|
||||
|
||||
// Apply gamma correction per WCAG 2.0
|
||||
func adjust(_ component: CGFloat) -> Double {
|
||||
let c = Double(component)
|
||||
return c <= 0.03928 ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4)
|
||||
}
|
||||
|
||||
return 0.2126 * adjust(r) + 0.7152 * adjust(g) + 0.0722 * adjust(b)
|
||||
}
|
||||
|
||||
/// Returns true if the color is considered "light" (needs dark text for contrast)
|
||||
var isLight: Bool {
|
||||
luminance > 0.5
|
||||
}
|
||||
|
||||
/// Returns black or white depending on which provides better contrast
|
||||
var contrastingTextColor: Color {
|
||||
isLight ? .black : .white
|
||||
}
|
||||
}
|
||||
|
||||
extension Color: @retroactive RawRepresentable {
|
||||
// TODO: Sort out alpha
|
||||
public init?(rawValue: Int) {
|
||||
|
||||
Reference in New Issue
Block a user