Skip to content

Commit 8cfba33

Browse files
authored
feat: add raw and semantic tokens of color mode (#599) (#601)
Closes #509 Acked-by: Ludovic Pinel <[email protected]> Signed-off-by: Pierre-Yves Lapersonne <[email protected]>
1 parent cbba364 commit 8cfba33

24 files changed

+1337
-5
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Added
1010

11+
- [Library] Raw and semantic tokens for color mode ([#599](https://github.com/Orange-OpenSource/ouds-ios/issues/599))
1112
- [Library] `Divider` component tokens (tokens library v0.9.0)
1213
- [Library] `dimension1250` raw token of dimension (tokens library v0.9.0)
1314
- [Library] Support of arabic language ([#552](https://github.com/Orange-OpenSource/ouds-ios/issues/552))

OUDS/Core/OUDS/Sources/OUDSTheme/OUDSTheme.swift

+6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ open class OUDSTheme: @unchecked Sendable {
4343
/// All color semantic tokens exposed in one object
4444
public let colors: AllColorSemanticTokensProvider
4545

46+
/// All color mode semantic tokens exposed in one object
47+
public let colorModes: AllColorModeSemanticTokensProvider
48+
4649
/// All elevation semantic tokens exposed in one object
4750
public let elevations: AllElevationSemanticTokensProvider
4851

@@ -120,6 +123,7 @@ open class OUDSTheme: @unchecked Sendable {
120123
/// - Parameters:
121124
/// - borders: All semantic tokens of borders
122125
/// - colors: All semantic tokens of colors
126+
/// - colorModes: All semantic tokens of color modes
123127
/// - elevations: All semantic tokens of elevations
124128
/// - fonts: All semantic tokens of fonts
125129
/// - grids: All semantic tokens of grids
@@ -144,6 +148,7 @@ open class OUDSTheme: @unchecked Sendable {
144148
/// - fontFamily: Set `nil` if system font to use, otherwise use the `FontFamilySemanticToken` you want to apply
145149
public init(borders: AllBorderSemanticTokensProvider,
146150
colors: AllColorSemanticTokensProvider,
151+
colorModes: AllColorModeSemanticTokensProvider,
147152
elevations: AllElevationSemanticTokensProvider,
148153
fonts: AllFontSemanticTokensProvider,
149154
grids: AllGridSemanticTokensProvider,
@@ -170,6 +175,7 @@ open class OUDSTheme: @unchecked Sendable {
170175
// Save semantic tokens providers
171176
self.borders = borders
172177
self.colors = colors
178+
self.colorModes = colorModes
173179
self.elevations = elevations
174180
self.fonts = fonts
175181
self.grids = grids

OUDS/Core/OUDS/Sources/OUDSTheme/TokensProviders.swift

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public protocol AllBorderSemanticTokensProvider: TokensProvider, BorderSemanticT
2828
/// Something which provides all semantic tokens of colors
2929
public protocol AllColorSemanticTokensProvider: TokensProvider, ColorSemanticTokens, ColorMultipleSemanticTokens { }
3030

31+
/// Something which provides all semantic tokens of colors modes
32+
public protocol AllColorModeSemanticTokensProvider: TokensProvider, ColorModeSemanticTokens, ColorModeMultipleSemanticTokens { }
33+
3134
/// Something which provides all semantic tokens of elevation
3235
public protocol AllElevationSemanticTokensProvider: TokensProvider, ElevationSemanticTokens, ElevationCompositeSemanticTokens, ElevationMultipleSemanticTokens { }
3336

OUDS/Core/Themes/Orange/Sources/OrangeTheme.swift

+4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ open class OrangeTheme: OUDSTheme, @unchecked Sendable {
8585
/// - Parameters:
8686
/// - borders: All semantic tokens of borders
8787
/// - colors: All semantic tokens of colors
88+
/// - colorModes: All semantic tokens of color modes
8889
/// - elevations: All semantic tokens of elevations
8990
/// - fonts: All semantic tokens of fonts
9091
/// - grids: All semantic tokens of grids
@@ -109,6 +110,7 @@ open class OrangeTheme: OUDSTheme, @unchecked Sendable {
109110
/// - fontFamily: Set `nil` if system font to use, otherwise use the `FontFamilySemanticToken` you want to apply
110111
override public init(borders: AllBorderSemanticTokensProvider? = nil,
111112
colors: AllColorSemanticTokensProvider? = nil,
113+
colorModes: AllColorModeSemanticTokensProvider? = nil,
112114
elevations: AllElevationSemanticTokensProvider? = nil,
113115
fonts: AllFontSemanticTokensProvider? = nil,
114116
grids: AllGridSemanticTokensProvider? = nil,
@@ -134,6 +136,7 @@ open class OrangeTheme: OUDSTheme, @unchecked Sendable {
134136

135137
let borders = (borders ?? OrangeThemeBorderSemanticTokensProvider())
136138
let colors = (colors ?? OrangeThemeColorSemanticTokensProvider())
139+
let colorModes = (colorModes ?? OrangeThemeColorModeSemanticTokensProvider())
137140
let elevations = (elevations ?? OrangeThemeElevationSemanticTokensProvider())
138141
let fonts = (fonts ?? OrangeThemeFontSemanticTokensProvider())
139142
let grids = (grids ?? OrangeThemeGridSemanticTokensProvider())
@@ -159,6 +162,7 @@ open class OrangeTheme: OUDSTheme, @unchecked Sendable {
159162

160163
super.init(borders: borders,
161164
colors: colors,
165+
colorModes: colorModes,
162166
elevations: elevations,
163167
fonts: fonts,
164168
grids: grids,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//
2+
// Software Name: OUDS iOS
3+
// SPDX-FileCopyrightText: Copyright (c) Orange SA
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This software is distributed under the MIT license,
7+
// the text of which is available at https://opensource.org/license/MIT/
8+
// or see the "LICENSE" file for more details.
9+
//
10+
// Authors: See CONTRIBUTORS.txt
11+
// Software description: A SwiftUI components library with code examples for Orange Unified Design System
12+
//
13+
14+
import OUDS
15+
import OUDSFoundations
16+
17+
// swiftlint:disable type_name
18+
19+
/// A class which wraps all **color mode semantic tokens**, *multiple* or not, and expose them.
20+
/// This provider should be integrated as a `AllColorModeSemanticTokensProvider` implementation inside `OUDSTheme` so as to provide
21+
/// all tokens to the users. It helps users to override some of the tokens and assign them to an `OUDSTheme` implementation to use.
22+
///
23+
/// ```swift
24+
/// // Define your own provider for color mode semantic tokens
25+
/// class CustomColorModeTokensProviderr: OrangeThemeColorModeSemanticTokensProvider {
26+
///
27+
/// // Then override the color mode semantic tokens you want, using the color mode raw tokens available
28+
///
29+
/// override var modeOnBrandSecondaryLight: ColorModeSemanticToken {
30+
/// ColorModeRawTokens.light
31+
/// }
32+
///
33+
/// override var modeOnBrandSecondaryDark: ColorModeSemanticToken {
34+
/// ColorModeRawTokens.dark
35+
/// }
36+
///
37+
/// override var modeOnStatusAccentEmphasized: MultipleColorModeSemanticTokens {
38+
/// MultipleColorModeSemanticTokens(light: ColorModeRawTokens.dark, dark: ColorModeRawTokens.light)
39+
/// }
40+
/// }
41+
/// ```
42+
///
43+
/// Then, you can give this `CustomColorTokensProvider` to your own theme implementation:
44+
///
45+
/// ```swift
46+
/// class LocalTheme: OrangeTheme {
47+
///
48+
/// override init() {
49+
/// super.init(colorModes: CustomColorModeTokensProviderr())
50+
/// }
51+
/// }
52+
/// ```
53+
///
54+
/// or to an already existing theme for example:
55+
///
56+
/// ```swift
57+
/// OrangeTheme(colorModes: CustomColorModeTokensProviderr())
58+
/// ```
59+
///
60+
/// - Since: 0.13.0
61+
open class OrangeThemeColorModeSemanticTokensProvider: AllColorModeSemanticTokensProvider {
62+
63+
/// Intializes the provider
64+
public init() {
65+
OL.debug("Init of OrangeThemeColorModeSemanticTokensProvider")
66+
}
67+
68+
deinit{ }
69+
70+
// ଘ( ・ω・)_/゚・:*:・。☆
71+
// Note: So as to help the integration of generated code produced by the tokenator
72+
// the implemention of ColorModeSemanticTokens and ColorModeMultipleSemanticTokens are not here
73+
// but in Core/Themes/Orange/Values/SemanticTokens/OrangeTheme+ColorModeMultipleSemanticTokens.swift
74+
// and in Core/Themes/Orange/Values/SemanticTokens/OrangeTheme+ColorModeSemanticTokens.swift
75+
// This declaration of OrangeThemeColorModeSemanticTokensProvider is here to allow to write documentation.
76+
}
77+
78+
// swiftlint:enable type_name
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//
2+
// Software Name: OUDS iOS
3+
// SPDX-FileCopyrightText: Copyright (c) Orange SA
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This software is distributed under the MIT license,
7+
// the text of which is available at https://opensource.org/license/MIT/
8+
// or see the "LICENSE" file for more details.
9+
//
10+
// Authors: See CONTRIBUTORS.txt
11+
// Software description: A SwiftUI components library with code examples for Orange Unified Design System
12+
//
13+
14+
import Foundation
15+
import OUDSTokensRaw
16+
import OUDSTokensSemantic
17+
import SwiftUI
18+
19+
// [File not generated by the tokenator]
20+
// Create an issue for update https://github.com/Orange-OpenSource/ouds-ios/issues/new?template=token_update.yml
21+
22+
// swiftlint:disable line_length
23+
24+
/// Defines provider objects for `ColorModeSemanticTokens` so as to pack them as light and dark mode colors.
25+
/// These values can be overriden inside `OrangeThemeColorModeSemanticTokensProvider` subclasses (in extensions or not, in the same module or not) thanks to the `@objc open` combination.
26+
extension OrangeThemeColorModeSemanticTokensProvider: ColorModeMultipleSemanticTokens {
27+
28+
// MARK: - Multiple tokens
29+
30+
@objc open var modeOnBrandPrimary: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnBrandPrimaryLight, dark: modeOnBrandPrimaryDark) }
31+
32+
@objc open var modeOnBrandSecondary: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnBrandSecondaryLight, dark: modeOnBrandSecondaryDark) }
33+
34+
@objc open var modeOnBrandTertiary: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnBrandTertiaryLight, dark: modeOnBrandTertiaryDark) }
35+
36+
@objc open var modeOnStatusAccentEmphasized: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusAccentEmphasizedLight, dark: modeOnStatusAccentEmphasizedDark) }
37+
38+
@objc open var modeOnStatusAccentMuted: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusAccentMutedLight, dark: modeOnStatusAccentMutedDark) }
39+
40+
@objc open var modeOnStatusInfoEmphasized: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusInfoEmphasizedLight, dark: modeOnStatusInfoEmphasizedDark) }
41+
42+
@objc open var modeOnStatusInfoMuted: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusInfoMutedLight, dark: modeOnStatusInfoMutedDark) }
43+
44+
@objc open var modeOnStatusNegativeEmphasized: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusNegativeEmphasizedLight, dark: modeOnStatusNegativeEmphasizedDark) }
45+
46+
@objc open var modeOnStatusNegativeMuted: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusNegativeMutedLight, dark: modeOnStatusNegativeMutedDark) }
47+
48+
@objc open var modeOnStatusNeutralEmphasized: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusNeutralEmphasizedLight, dark: modeOnStatusNeutralEmphasizedDark) }
49+
50+
@objc open var modeOnStatusNeutralMuted: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusNeutralMutedLight, dark: modeOnStatusNeutralMutedDark) }
51+
52+
@objc open var modeOnStatusPositiveEmphasized: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusPositiveEmphasizedLight, dark: modeOnStatusPositiveEmphasizedDark) }
53+
54+
@objc open var modeOnStatusPositiveMuted: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusPositiveMutedLight, dark: modeOnStatusPositiveMutedDark) }
55+
56+
@objc open var modeOnStatusWarningEmphasized: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusWarningEmphasizedLight, dark: modeOnStatusWarningEmphasizedDark) }
57+
58+
@objc open var modeOnStatusWarningMuted: MultipleColorModeSemanticTokens { MultipleColorModeSemanticTokens(light: modeOnStatusWarningMutedLight, dark: modeOnStatusWarningMutedDark) }
59+
60+
// MARK: - Additional rules
61+
62+
/// Depending to the given `mode`, should return the SwfitUI `ColorScheme` to consider.
63+
/// For Orange theme, the rules are:
64+
/// - if light version is dark mode and dark version is light mode, reverse the color scheme
65+
/// - if light and dark versions are light mode, return light color scheme
66+
/// - if light and dark versions are dark mode, return dark color scheme
67+
/// - otherwise return current color scheme
68+
///
69+
/// - Parameters:
70+
/// - mode: The color mode token to test
71+
/// - current: The current color scheme
72+
/// - Returns: The color scheme to consider depending to the theme rules
73+
public func useColorScheme(for mode: MultipleColorModeSemanticTokens,
74+
_ current: ColorScheme) -> ColorScheme {
75+
76+
let lightColorScheme = ColorModeRawTokens.colorScheme(for: mode.light)
77+
let darkColorScheme = ColorModeRawTokens.colorScheme(for: mode.dark)
78+
79+
// Reverse the color scheme to apply
80+
if lightColorScheme == .dark && darkColorScheme == .light {
81+
return (current == .light ? .dark : .light)
82+
}
83+
84+
// Force light
85+
if lightColorScheme == .light && darkColorScheme == .light {
86+
return .light
87+
}
88+
89+
// Force dark
90+
if lightColorScheme == .dark && darkColorScheme == .dark {
91+
return .dark
92+
}
93+
94+
// Otherwise use device configuration
95+
return current
96+
}
97+
98+
/// Depending to the given `mode`, should return a flag saying if monochrome mode must be considered.
99+
/// For Orange theme, the rule is :
100+
/// - if both light and dark versions are monochrome, returns true, otherwise false
101+
///
102+
/// - Parameter mode: The color mode token to test
103+
/// - Returns: The flag for monochrome mode depending to the theme rules
104+
public func isMonochrome(mode: MultipleColorModeSemanticTokens) -> Bool {
105+
let lightIsMonochrome = ColorModeRawTokens.isMonochrome(mode: mode.light)
106+
let darkIsMonochrome = ColorModeRawTokens.isMonochrome(mode: mode.dark)
107+
return lightIsMonochrome == true && darkIsMonochrome == true
108+
}
109+
}
110+
111+
// swiftlint:enable line_length
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// Software Name: OUDS iOS
3+
// SPDX-FileCopyrightText: Copyright (c) Orange SA
4+
// SPDX-License-Identifier: MIT
5+
//
6+
// This software is distributed under the MIT license,
7+
// the text of which is available at https://opensource.org/license/MIT/
8+
// or see the "LICENSE" file for more details.
9+
//
10+
// Authors: See CONTRIBUTORS.txt
11+
// Software description: A SwiftUI components library with code examples for Orange Unified Design System
12+
//
13+
14+
import Foundation
15+
import OUDSTokensRaw
16+
import OUDSTokensSemantic
17+
18+
// 🧱 Tokens version: 0.11.0
19+
// 🤖 Generated by Tokenator
20+
21+
extension OrangeThemeColorModeSemanticTokensProvider: ColorModeSemanticTokens {
22+
@objc open var modeOnBrandPrimaryLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
23+
@objc open var modeOnBrandSecondaryLight: ColorModeSemanticToken { ColorModeRawTokens.undefined }
24+
@objc open var modeOnBrandTertiaryLight: ColorModeSemanticToken { ColorModeRawTokens.undefined }
25+
@objc open var modeOnStatusAccentEmphasizedLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
26+
@objc open var modeOnStatusAccentMutedLight: ColorModeSemanticToken { ColorModeRawTokens.light }
27+
@objc open var modeOnStatusInfoEmphasizedLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
28+
@objc open var modeOnStatusInfoMutedLight: ColorModeSemanticToken { ColorModeRawTokens.light }
29+
@objc open var modeOnStatusNegativeEmphasizedLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeDark }
30+
@objc open var modeOnStatusNegativeMutedLight: ColorModeSemanticToken { ColorModeRawTokens.light }
31+
@objc open var modeOnStatusNeutralEmphasizedLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeDark }
32+
@objc open var modeOnStatusNeutralMutedLight: ColorModeSemanticToken { ColorModeRawTokens.light }
33+
@objc open var modeOnStatusPositiveEmphasizedLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
34+
@objc open var modeOnStatusPositiveMutedLight: ColorModeSemanticToken { ColorModeRawTokens.light }
35+
@objc open var modeOnStatusWarningEmphasizedLight: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
36+
@objc open var modeOnStatusWarningMutedLight: ColorModeSemanticToken { ColorModeRawTokens.light }
37+
@objc open var modeOnBrandPrimaryDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
38+
@objc open var modeOnBrandSecondaryDark: ColorModeSemanticToken { ColorModeRawTokens.undefined }
39+
@objc open var modeOnBrandTertiaryDark: ColorModeSemanticToken { ColorModeRawTokens.undefined }
40+
@objc open var modeOnStatusAccentEmphasizedDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
41+
@objc open var modeOnStatusAccentMutedDark: ColorModeSemanticToken { ColorModeRawTokens.dark }
42+
@objc open var modeOnStatusInfoEmphasizedDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
43+
@objc open var modeOnStatusInfoMutedDark: ColorModeSemanticToken { ColorModeRawTokens.dark }
44+
@objc open var modeOnStatusNegativeEmphasizedDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
45+
@objc open var modeOnStatusNegativeMutedDark: ColorModeSemanticToken { ColorModeRawTokens.dark }
46+
@objc open var modeOnStatusNeutralEmphasizedDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
47+
@objc open var modeOnStatusNeutralMutedDark: ColorModeSemanticToken { ColorModeRawTokens.dark }
48+
@objc open var modeOnStatusPositiveEmphasizedDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
49+
@objc open var modeOnStatusPositiveMutedDark: ColorModeSemanticToken { ColorModeRawTokens.dark }
50+
@objc open var modeOnStatusWarningEmphasizedDark: ColorModeSemanticToken { ColorModeRawTokens.monochromeLight }
51+
@objc open var modeOnStatusWarningMutedDark: ColorModeSemanticToken { ColorModeRawTokens.dark }
52+
}

0 commit comments

Comments
 (0)