From 0e6e9a1a6ed50cfe65e34760a9de4f72e5529aa4 Mon Sep 17 00:00:00 2001 From: Mike Schreiber Date: Fri, 8 Nov 2024 13:38:04 -0800 Subject: [PATCH] Fix dark mode issues with new color system (#2105) --- .../Core/Extensions/Color+Extensions.swift | 24 ++ .../Core/FluentTheme+Tokens.swift | 390 +++++++++--------- .../Core/Theme/FluentTheme+UIKit.swift | 2 +- .../FluentUI_iOS/Core/Theme/FluentTheme.swift | 17 +- 4 files changed, 230 insertions(+), 203 deletions(-) diff --git a/Sources/FluentUI_iOS/Core/Extensions/Color+Extensions.swift b/Sources/FluentUI_iOS/Core/Extensions/Color+Extensions.swift index f585e6718..23473a40a 100644 --- a/Sources/FluentUI_iOS/Core/Extensions/Color+Extensions.swift +++ b/Sources/FluentUI_iOS/Core/Extensions/Color+Extensions.swift @@ -33,10 +33,34 @@ extension Color { darkElevated: Color? = nil) { let dynamicColor = DynamicColor(light: light, dark: dark, darkElevated: darkElevated) + self.init(dynamicColor: dynamicColor) + } + + /// Creates a custom `Color` from a prebuilt `DynamicColor` structure. + /// + /// - Parameter dynamicColor: A dynmic color structure that describes the `Color` to be created. + init(dynamicColor: DynamicColor) { if #available(iOS 17, *) { self.init(dynamicColor) } else { self.init(uiColor: UIColor(dynamicColor: dynamicColor)) } } + + var dynamicColor: DynamicColor { + if #available(iOS 17, *) { + var lightEnvironment = EnvironmentValues.init() + lightEnvironment.colorScheme = .light + + var darkEnvironment = EnvironmentValues.init() + darkEnvironment.colorScheme = .dark + + return DynamicColor(light: Color(self.resolve(in: lightEnvironment)), + dark: Color(self.resolve(in: darkEnvironment))) + } else { + let uiColor = UIColor(self) + return DynamicColor(light: Color(uiColor.light), + dark: Color(uiColor.dark)) + } + } } diff --git a/Sources/FluentUI_iOS/Core/FluentTheme+Tokens.swift b/Sources/FluentUI_iOS/Core/FluentTheme+Tokens.swift index 070644034..cea14a0ac 100644 --- a/Sources/FluentUI_iOS/Core/FluentTheme+Tokens.swift +++ b/Sources/FluentUI_iOS/Core/FluentTheme+Tokens.swift @@ -150,7 +150,7 @@ public extension FluentTheme { /// - Parameter token: The `ColorsTokens` value to be retrieved. /// - Returns: A `Color` for the given token. func swiftUIColor(_ token: ColorToken) -> Color { - return colorTokenSet[token] + return Color(dynamicColor: colorTokenSet[token]) } /// Returns the shadow value for the given token. @@ -176,289 +176,289 @@ public extension FluentTheme { /// - Parameter token: The `GradientTokens` value to be retrieved. /// - Returns: An array of `Color` values for the given token. func gradient(_ token: GradientToken) -> [Color] { - return gradientTokenSet[token] + return gradientTokenSet[token].map { Color(dynamicColor: $0) } } } extension FluentTheme { - static func defaultColor(_ token: FluentTheme.ColorToken) -> Color { + static func defaultColor(_ token: FluentTheme.ColorToken) -> DynamicColor { switch token { case .foreground1: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey14), - dark: GlobalTokens.neutralSwiftUIColor(.white)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey14), + dark: GlobalTokens.neutralSwiftUIColor(.white)) case .foreground2: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey38), - dark: GlobalTokens.neutralSwiftUIColor(.grey84)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey38), + dark: GlobalTokens.neutralSwiftUIColor(.grey84)) case .foreground3: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey50), - dark: GlobalTokens.neutralSwiftUIColor(.grey68)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey50), + dark: GlobalTokens.neutralSwiftUIColor(.grey68)) case .foregroundDisabled1: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey74), - dark: GlobalTokens.neutralSwiftUIColor(.grey36)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey74), + dark: GlobalTokens.neutralSwiftUIColor(.grey36)) case .foregroundDisabled2: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.grey18)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.grey18)) case .foregroundOnColor: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.black)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.black)) case .brandForegroundTint: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm60), - dark: GlobalTokens.brandSwiftUIColor(.comm130)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm60), + dark: GlobalTokens.brandSwiftUIColor(.comm130)) case .brandForeground1: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm80), - dark: GlobalTokens.brandSwiftUIColor(.comm100)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm80), + dark: GlobalTokens.brandSwiftUIColor(.comm100)) case .brandForeground1Pressed: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm50), - dark: GlobalTokens.brandSwiftUIColor(.comm140)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm50), + dark: GlobalTokens.brandSwiftUIColor(.comm140)) case .brandForeground1Selected: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm60), - dark: GlobalTokens.brandSwiftUIColor(.comm120)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm60), + dark: GlobalTokens.brandSwiftUIColor(.comm120)) case .brandForegroundDisabled1: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm90)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm90)) case .brandForegroundDisabled2: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm140), - dark: GlobalTokens.brandSwiftUIColor(.comm40)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm140), + dark: GlobalTokens.brandSwiftUIColor(.comm40)) case .brandGradient1: - return Color(light: GlobalTokens.brandSwiftUIColor(.gradientPrimaryLight), - dark: GlobalTokens.brandSwiftUIColor(.gradientPrimaryDark)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.gradientPrimaryLight), + dark: GlobalTokens.brandSwiftUIColor(.gradientPrimaryDark)) case .brandGradient2: - return Color(light: GlobalTokens.brandSwiftUIColor(.gradientSecondaryLight), - dark: GlobalTokens.brandSwiftUIColor(.gradientSecondaryDark)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.gradientSecondaryLight), + dark: GlobalTokens.brandSwiftUIColor(.gradientSecondaryDark)) case .brandGradient3: - return Color(light: GlobalTokens.brandSwiftUIColor(.gradientTertiaryLight), - dark: GlobalTokens.brandSwiftUIColor(.gradientTertiaryDark)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.gradientTertiaryLight), + dark: GlobalTokens.brandSwiftUIColor(.gradientTertiaryDark)) case .foregroundDarkStatic: - return Color(light: GlobalTokens.neutralSwiftUIColor(.black), - dark: GlobalTokens.neutralSwiftUIColor(.black)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.black), + dark: GlobalTokens.neutralSwiftUIColor(.black)) case .foregroundLightStatic: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.white)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.white)) case .background1: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.black), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey4)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.black), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey4)) case .background1Pressed: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey88), - dark: GlobalTokens.neutralSwiftUIColor(.grey18), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey18)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey88), + dark: GlobalTokens.neutralSwiftUIColor(.grey18), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey18)) case .background1Selected: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey92), - dark: GlobalTokens.neutralSwiftUIColor(.grey14), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey14)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey92), + dark: GlobalTokens.neutralSwiftUIColor(.grey14), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey14)) case .background2: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.grey12), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey16)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.grey12), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey16)) case .background2Pressed: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey88), - dark: GlobalTokens.neutralSwiftUIColor(.grey30), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey88), + dark: GlobalTokens.neutralSwiftUIColor(.grey30), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) case .background2Selected: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey92), - dark: GlobalTokens.neutralSwiftUIColor(.grey26), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey26)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey92), + dark: GlobalTokens.neutralSwiftUIColor(.grey26), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey26)) case .background3: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.grey16), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey20)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.grey16), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey20)) case .background3Pressed: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey88), - dark: GlobalTokens.neutralSwiftUIColor(.grey34), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey34)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey88), + dark: GlobalTokens.neutralSwiftUIColor(.grey34), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey34)) case .background3Selected: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey92), - dark: GlobalTokens.neutralSwiftUIColor(.grey30), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey92), + dark: GlobalTokens.neutralSwiftUIColor(.grey30), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) case .background4: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey98), - dark: GlobalTokens.neutralSwiftUIColor(.grey20), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey24)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey98), + dark: GlobalTokens.neutralSwiftUIColor(.grey20), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey24)) case .background4Pressed: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey86), - dark: GlobalTokens.neutralSwiftUIColor(.grey38), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey38)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey86), + dark: GlobalTokens.neutralSwiftUIColor(.grey38), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey38)) case .background4Selected: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey90), - dark: GlobalTokens.neutralSwiftUIColor(.grey34), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey34)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey90), + dark: GlobalTokens.neutralSwiftUIColor(.grey34), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey34)) case .background5: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey94), - dark: GlobalTokens.neutralSwiftUIColor(.grey24), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey28)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey94), + dark: GlobalTokens.neutralSwiftUIColor(.grey24), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey28)) case .background5Pressed: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey82), - dark: GlobalTokens.neutralSwiftUIColor(.grey42), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey42)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey82), + dark: GlobalTokens.neutralSwiftUIColor(.grey42), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey42)) case .background5Selected: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey86), - dark: GlobalTokens.neutralSwiftUIColor(.grey38), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey38)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey86), + dark: GlobalTokens.neutralSwiftUIColor(.grey38), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey38)) case .background6: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey82), - dark: GlobalTokens.neutralSwiftUIColor(.grey36), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey40)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey82), + dark: GlobalTokens.neutralSwiftUIColor(.grey36), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey40)) case .backgroundDisabled: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey88), - dark: GlobalTokens.neutralSwiftUIColor(.grey32), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey32)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey88), + dark: GlobalTokens.neutralSwiftUIColor(.grey32), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey32)) case .brandBackgroundTint: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm150), - dark: GlobalTokens.brandSwiftUIColor(.comm40)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm150), + dark: GlobalTokens.brandSwiftUIColor(.comm40)) case .brandBackground1: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm80), - dark: GlobalTokens.brandSwiftUIColor(.comm100)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm80), + dark: GlobalTokens.brandSwiftUIColor(.comm100)) case .brandBackground1Pressed: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm50), - dark: GlobalTokens.brandSwiftUIColor(.comm140)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm50), + dark: GlobalTokens.brandSwiftUIColor(.comm140)) case .brandBackground1Selected: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm60), - dark: GlobalTokens.brandSwiftUIColor(.comm120)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm60), + dark: GlobalTokens.brandSwiftUIColor(.comm120)) case .brandBackground2: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm70)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm70)) case .brandBackground2Pressed: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm40)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm40)) case .brandBackground2Selected: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm80)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm80)) case .brandBackground3: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm60), - dark: GlobalTokens.brandSwiftUIColor(.comm120)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm60), + dark: GlobalTokens.brandSwiftUIColor(.comm120)) case .brandBackgroundDisabled: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm140), - dark: GlobalTokens.brandSwiftUIColor(.comm40)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm140), + dark: GlobalTokens.brandSwiftUIColor(.comm40)) case .stencil1: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey90), - dark: GlobalTokens.neutralSwiftUIColor(.grey34)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey90), + dark: GlobalTokens.neutralSwiftUIColor(.grey34)) case .stencil2: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey98), - dark: GlobalTokens.neutralSwiftUIColor(.grey20)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey98), + dark: GlobalTokens.neutralSwiftUIColor(.grey20)) case .backgroundCanvas: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey96), - dark: GlobalTokens.neutralSwiftUIColor(.grey8), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey14)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey96), + dark: GlobalTokens.neutralSwiftUIColor(.grey8), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey14)) case .backgroundDarkStatic: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey14), - dark: GlobalTokens.neutralSwiftUIColor(.grey24), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey14), + dark: GlobalTokens.neutralSwiftUIColor(.grey24), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) case .backgroundInverted: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey46), - dark: GlobalTokens.neutralSwiftUIColor(.grey72), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey78)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey46), + dark: GlobalTokens.neutralSwiftUIColor(.grey72), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey78)) case .backgroundLightStatic: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.white), - darkElevated: GlobalTokens.neutralSwiftUIColor(.white)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.white), + darkElevated: GlobalTokens.neutralSwiftUIColor(.white)) case .backgroundLightStaticDisabled: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.grey68), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey42)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.grey68), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey42)) case .stroke1: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey82), - dark: GlobalTokens.neutralSwiftUIColor(.grey30), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey36)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey82), + dark: GlobalTokens.neutralSwiftUIColor(.grey30), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey36)) case .stroke1Pressed: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey70), - dark: GlobalTokens.neutralSwiftUIColor(.grey48)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey70), + dark: GlobalTokens.neutralSwiftUIColor(.grey48)) case .stroke2: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey88), - dark: GlobalTokens.neutralSwiftUIColor(.grey24), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey88), + dark: GlobalTokens.neutralSwiftUIColor(.grey24), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey30)) case .strokeAccessible: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey38), - dark: GlobalTokens.neutralSwiftUIColor(.grey62), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey68)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey38), + dark: GlobalTokens.neutralSwiftUIColor(.grey62), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey68)) case .strokeFocus1: - return Color(light: GlobalTokens.neutralSwiftUIColor(.white), - dark: GlobalTokens.neutralSwiftUIColor(.black)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.white), + dark: GlobalTokens.neutralSwiftUIColor(.black)) case .strokeFocus2: - return Color(light: GlobalTokens.neutralSwiftUIColor(.black), - dark: GlobalTokens.neutralSwiftUIColor(.white)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.black), + dark: GlobalTokens.neutralSwiftUIColor(.white)) case .strokeDisabled: - return Color(light: GlobalTokens.neutralSwiftUIColor(.grey88), - dark: GlobalTokens.neutralSwiftUIColor(.grey26), - darkElevated: GlobalTokens.neutralSwiftUIColor(.grey32)) + return DynamicColor(light: GlobalTokens.neutralSwiftUIColor(.grey88), + dark: GlobalTokens.neutralSwiftUIColor(.grey26), + darkElevated: GlobalTokens.neutralSwiftUIColor(.grey32)) case .brandStroke1: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm80), - dark: GlobalTokens.brandSwiftUIColor(.comm100)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm80), + dark: GlobalTokens.brandSwiftUIColor(.comm100)) case .brandStroke1Pressed: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm50), - dark: GlobalTokens.brandSwiftUIColor(.comm140)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm50), + dark: GlobalTokens.brandSwiftUIColor(.comm140)) case .brandStroke1Selected: - return Color(light: GlobalTokens.brandSwiftUIColor(.comm60), - dark: GlobalTokens.brandSwiftUIColor(.comm120)) + return DynamicColor(light: GlobalTokens.brandSwiftUIColor(.comm60), + dark: GlobalTokens.brandSwiftUIColor(.comm120)) case .dangerBackground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .tint60), - dark: GlobalTokens.sharedSwiftUIColor(.red, .shade40)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .tint60), + dark: GlobalTokens.sharedSwiftUIColor(.red, .shade40)) case .dangerBackground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.red, .shade10)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.red, .shade10)) case .dangerForeground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .shade10), - dark: GlobalTokens.sharedSwiftUIColor(.red, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .shade10), + dark: GlobalTokens.sharedSwiftUIColor(.red, .tint30)) case .dangerForeground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.red, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.red, .tint30)) case .dangerStroke1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .tint20), - dark: GlobalTokens.sharedSwiftUIColor(.red, .tint20)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .tint20), + dark: GlobalTokens.sharedSwiftUIColor(.red, .tint20)) case .dangerStroke2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.red, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.red, .tint30)) case .successBackground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.green, .tint60), - dark: GlobalTokens.sharedSwiftUIColor(.green, .shade40)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.green, .tint60), + dark: GlobalTokens.sharedSwiftUIColor(.green, .shade40)) case .successBackground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.green, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.green, .shade10)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.green, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.green, .shade10)) case .successForeground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.green, .shade10), - dark: GlobalTokens.sharedSwiftUIColor(.green, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.green, .shade10), + dark: GlobalTokens.sharedSwiftUIColor(.green, .tint30)) case .successForeground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.green, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.green, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.green, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.green, .tint30)) case .successStroke1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.green, .tint20), - dark: GlobalTokens.sharedSwiftUIColor(.green, .tint20)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.green, .tint20), + dark: GlobalTokens.sharedSwiftUIColor(.green, .tint20)) case .severeBackground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint60), - dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade40)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint60), + dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade40)) case .severeBackground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade10)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade10)) case .severeForeground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade10), - dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade10), + dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint30)) case .severeForeground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade20), - dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .shade20), + dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint30)) case .severeStroke1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint10), - dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint20)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint10), + dark: GlobalTokens.sharedSwiftUIColor(.darkOrange, .tint20)) case .warningBackground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.yellow, .tint60), - dark: GlobalTokens.sharedSwiftUIColor(.yellow, .shade40)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.yellow, .tint60), + dark: GlobalTokens.sharedSwiftUIColor(.yellow, .shade40)) case .warningBackground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.yellow, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.yellow, .shade10)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.yellow, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.yellow, .shade10)) case .warningForeground1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.yellow, .shade30), - dark: GlobalTokens.sharedSwiftUIColor(.yellow, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.yellow, .shade30), + dark: GlobalTokens.sharedSwiftUIColor(.yellow, .tint30)) case .warningForeground2: - return Color(light: GlobalTokens.sharedSwiftUIColor(.yellow, .shade30), - dark: GlobalTokens.sharedSwiftUIColor(.yellow, .tint30)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.yellow, .shade30), + dark: GlobalTokens.sharedSwiftUIColor(.yellow, .tint30)) case .warningStroke1: - return Color(light: GlobalTokens.sharedSwiftUIColor(.yellow, .shade30), - dark: GlobalTokens.sharedSwiftUIColor(.yellow, .shade20)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.yellow, .shade30), + dark: GlobalTokens.sharedSwiftUIColor(.yellow, .shade20)) case .presenceAway: - return Color(light: GlobalTokens.sharedSwiftUIColor(.marigold, .primary)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.marigold, .primary)) case .presenceDnd: - return Color(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.red, .tint10)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.red, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.red, .tint10)) case .presenceAvailable: - return Color(light: GlobalTokens.sharedSwiftUIColor(.lightGreen, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.lightGreen, .tint20)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.lightGreen, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.lightGreen, .tint20)) case .presenceOof: - return Color(light: GlobalTokens.sharedSwiftUIColor(.berry, .primary), - dark: GlobalTokens.sharedSwiftUIColor(.berry, .tint20)) + return DynamicColor(light: GlobalTokens.sharedSwiftUIColor(.berry, .primary), + dark: GlobalTokens.sharedSwiftUIColor(.berry, .tint20)) } } @@ -584,7 +584,7 @@ extension FluentTheme { } /// Derives its default values from the theme's `colorTokenSet` values - static func defaultGradientColor(_ token: GradientToken, colorTokenSet: TokenSet) -> [Color] { + static func defaultGradientColor(_ token: GradientToken, colorTokenSet: TokenSet) -> [DynamicColor] { switch token { case .flair: return [colorTokenSet[.brandGradient1], diff --git a/Sources/FluentUI_iOS/Core/Theme/FluentTheme+UIKit.swift b/Sources/FluentUI_iOS/Core/Theme/FluentTheme+UIKit.swift index ad7976429..dd7080352 100644 --- a/Sources/FluentUI_iOS/Core/Theme/FluentTheme+UIKit.swift +++ b/Sources/FluentUI_iOS/Core/Theme/FluentTheme+UIKit.swift @@ -52,7 +52,7 @@ public extension FluentTheme { /// - Returns: A `UIColor` for the given token. @objc(colorForToken:) func color(_ token: ColorToken) -> UIColor { - return UIColor(swiftUIColor(token)) + return UIColor(dynamicColor: colorTokenSet[token]) } /// Returns the font value for the given token. diff --git a/Sources/FluentUI_iOS/Core/Theme/FluentTheme.swift b/Sources/FluentUI_iOS/Core/Theme/FluentTheme.swift index ce261a69a..34459fa01 100644 --- a/Sources/FluentUI_iOS/Core/Theme/FluentTheme.swift +++ b/Sources/FluentUI_iOS/Core/Theme/FluentTheme.swift @@ -41,18 +41,21 @@ public class FluentTheme: NSObject, ObservableObject { gradientOverrides: [GradientToken: [Color]]? = nil) { #if os(visionOS) // We have custom overrides for `defaultColors` in visionOS. - let defaultColorFunction: ((FluentTheme.ColorToken) -> Color) = FluentTheme.defaultColor_visionOS(_:) + let defaultColorFunction: ((FluentTheme.ColorToken) -> DynamicColor) = FluentTheme.defaultColor_visionOS(_:) #else - let defaultColorFunction: ((FluentTheme.ColorToken) -> Color) = FluentTheme.defaultColor(_:) + let defaultColorFunction: ((FluentTheme.ColorToken) -> DynamicColor) = FluentTheme.defaultColor(_:) #endif - let colorTokenSet = TokenSet(defaultColorFunction, colorOverrides) + let colorTokenSet = TokenSet( + defaultColorFunction, + colorOverrides?.mapValues { $0.dynamicColor } + ) let shadowTokenSet = TokenSet(FluentTheme.defaultShadow(_:), shadowOverrides) let typographyTokenSet = TokenSet(FluentTheme.defaultTypography(_:), typographyOverrides) - let gradientTokenSet = TokenSet({ [colorTokenSet] token in + let gradientTokenSet = TokenSet({ [colorTokenSet] token in // Reference the colorTokenSet as part of the gradient lookup return FluentTheme.defaultGradientColor(token, colorTokenSet: colorTokenSet) - }, gradientOverrides) + }, gradientOverrides?.mapValues { $0.map { $0.dynamicColor} }) self.colorTokenSet = colorTokenSet self.shadowTokenSet = shadowTokenSet @@ -107,10 +110,10 @@ public class FluentTheme: NSObject, ObservableObject { } // Token storage - let colorTokenSet: TokenSet + let colorTokenSet: TokenSet let shadowTokenSet: TokenSet let typographyTokenSet: TokenSet - let gradientTokenSet: TokenSet + let gradientTokenSet: TokenSet private func tokenKey(_ tokenSetType: ControlTokenSet.Type) -> String { return "\(tokenSetType)"