From 5bd516bea345ed9e308f3a23aef7bc7a45a85db9 Mon Sep 17 00:00:00 2001 From: LudovicPinel Date: Mon, 28 Oct 2024 13:31:45 +0100 Subject: [PATCH] feat: add new size semantic tokens in size tokens page (#245) (#255) Signed-off-by: Pierre-Yves Lapersonne Co-authored-by: Pierre-Yves Lapersonne Co-authored-by: Ludovic Pinel --- CHANGELOG.md | 1 + .../Multiples/MultipleSizeTokens.swift | 8 + .../Multiples/MultipleSpaceTokens.swift | 2 +- .../Multiples/MultipleTypographyTokens.swift | 9 +- Showcase/Showcase.xcodeproj/project.pbxproj | 36 ++- .../xcshareddata/swiftpm/Package.resolved | 6 +- .../NamedSize/NamedSize+IconDecorative.swift | 46 ++++ .../NamedSize+IconWithTypography.swift | 209 ++++++++++++++++++ .../Tokens/Dimension/Size/SizeTokenPage.swift | 94 ++++---- .../NamedTypography+Illustration.swift | 82 +++++++ .../NamedTypography/NamedTypography.swift | 97 ++++++++ .../Typography/TypographyTokenPage.swift | 144 +----------- .../Resources/en.lproj/Localizable.strings | 2 + 13 files changed, 551 insertions(+), 185 deletions(-) create mode 100644 Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconDecorative.swift create mode 100644 Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconWithTypography.swift create mode 100644 Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography+Illustration.swift create mode 100644 Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b69a76f6..7b3a94878 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- [DemoApp] Add new tokens in size tokens page ([#245](https://github.com/Orange-OpenSource/ouds-ios/issues/245)) - [Library] Semantic token `borderWidthFocusInset` (value of `borderWidth100`) ([#207](https://github.com/Orange-OpenSource/ouds-ios/issues/207), [#241](https://github.com/Orange-OpenSource/ouds-ios/issues/241)) - [Library] Semantic token `fontWeightCode` ([#242](https://github.com/Orange-OpenSource/ouds-ios/issues/242)) - [DemoApp] Update space tokens screen with all categories ([#178](https://github.com/Orange-OpenSource/ouds-ios/issues/178)) diff --git a/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSizeTokens.swift b/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSizeTokens.swift index 06dd0a043..8e14b32dd 100644 --- a/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSizeTokens.swift +++ b/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSizeTokens.swift @@ -12,6 +12,7 @@ // import Foundation +import SwiftUICore /// Kind of semantic tokens which will wrap a combination of `SizeSemanticToken` depending to viewports / size classes. /// Kind of composite token with multiple values, but not named "composite" because this word is already used in the design system. @@ -51,4 +52,11 @@ public final class MultipleSizeTokens: NSObject, Sendable { } return self.compact == other.compact && self.regular == other.regular } + + /// Returns the right dimension according to the `userInterfaceSizeClass`. + /// - Parameter userInterfaceSizeClass: The user interface size class (could be the horizontal or the vertical size class) + /// - Returns: The right size semantic token (pointing to the dimension raw token to use) + public func dimension(for userInterfaceSizeClass: UserInterfaceSizeClass) -> SizeSemanticToken { + userInterfaceSizeClass == .compact ? compact : regular + } } diff --git a/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSpaceTokens.swift b/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSpaceTokens.swift index 457ebbaa2..b27101e9e 100644 --- a/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSpaceTokens.swift +++ b/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleSpaceTokens.swift @@ -13,7 +13,7 @@ import Foundation import OUDSTokensRaw -import SwiftUI +import SwiftUICore /// Kind of semantic tokens which will wrap a combination of `DimensionRawToken` depending to size classes. /// Kind of composite token with multiple values, but not named "composite" because this word is already used in the design system. diff --git a/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleTypographyTokens.swift b/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleTypographyTokens.swift index ac8b20860..a3f4c4bf7 100644 --- a/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleTypographyTokens.swift +++ b/OUDS/Core/Tokens/SemanticTokens/Sources/Multiples/MultipleTypographyTokens.swift @@ -11,8 +11,8 @@ // Software description: A SwiftUI components library with code examples for Orange Unified Design System // -import Foundation import OUDSTokensRaw +import SwiftUICore /// Kind of semantic tokens which will wrap a combination of `TypographyCompositeRawToken` depending to size classes. /// Kind of composite token with multiple values, but not named "composite" because this word is already used in the design system. @@ -50,4 +50,11 @@ public final class MultipleTypographyTokens: NSObject, Sendable { guard let object = object as? MultipleTypographyTokens else { return false } return self.compact == object.compact && self.regular == object.regular } + + /// Returns the composite raw token of typography to use according to the `userInterfaceSizeClass` (i.e. `compact` or `regular`) + /// - Parameter userInterfaceSizeClass: The user interface size class + /// - Returns: The composite raw token to use (of type `TypographyCompositeRawToken`) + public func typographyToken(for userInterfaceSizeClass: UserInterfaceSizeClass) -> TypographyCompositeRawToken { + userInterfaceSizeClass == .compact ? compact : regular + } } diff --git a/Showcase/Showcase.xcodeproj/project.pbxproj b/Showcase/Showcase.xcodeproj/project.pbxproj index 03b20bfcc..e14e94fcc 100644 --- a/Showcase/Showcase.xcodeproj/project.pbxproj +++ b/Showcase/Showcase.xcodeproj/project.pbxproj @@ -52,6 +52,10 @@ 077CCE582CB426090059CC28 /* SpaceTokenPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077CCE522CB426090059CC28 /* SpaceTokenPage.swift */; }; 077CCE592CB426090059CC28 /* DimensionTokenElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077CCE542CB426090059CC28 /* DimensionTokenElement.swift */; }; 077CCE5C2CB431C50059CC28 /* ShowcaseVariantElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077CCE5B2CB431C50059CC28 /* ShowcaseVariantElement.swift */; }; + 0784B2712CCB86C500299C10 /* NamedSize+IconWithTypography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0784B26F2CCB86C500299C10 /* NamedSize+IconWithTypography.swift */; }; + 0784B2732CCB8CC800299C10 /* NamedSize+IconDecorative.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0784B2722CCB8CC800299C10 /* NamedSize+IconDecorative.swift */; }; + 0784B2762CCBD9C300299C10 /* NamedTypography.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0784B2752CCBD9C300299C10 /* NamedTypography.swift */; }; + 0784B2782CCBDD8900299C10 /* NamedTypography+Illustration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0784B2772CCBDD8900299C10 /* NamedTypography+Illustration.swift */; }; 07CF426B2CA30728000BD03E /* TokensPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07CF426A2CA30728000BD03E /* TokensPage.swift */; }; 07CF42722CA31AC3000BD03E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 07CF42712CA31AC3000BD03E /* Assets.xcassets */; }; 07CF42742CA3EC58000BD03E /* CardIllustration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07CF42732CA3EC58000BD03E /* CardIllustration.swift */; }; @@ -141,6 +145,10 @@ 077CCE522CB426090059CC28 /* SpaceTokenPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpaceTokenPage.swift; sourceTree = ""; }; 077CCE542CB426090059CC28 /* DimensionTokenElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DimensionTokenElement.swift; sourceTree = ""; }; 077CCE5B2CB431C50059CC28 /* ShowcaseVariantElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowcaseVariantElement.swift; sourceTree = ""; }; + 0784B26F2CCB86C500299C10 /* NamedSize+IconWithTypography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedSize+IconWithTypography.swift"; sourceTree = ""; }; + 0784B2722CCB8CC800299C10 /* NamedSize+IconDecorative.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedSize+IconDecorative.swift"; sourceTree = ""; }; + 0784B2752CCBD9C300299C10 /* NamedTypography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NamedTypography.swift; sourceTree = ""; }; + 0784B2772CCBDD8900299C10 /* NamedTypography+Illustration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedTypography+Illustration.swift"; sourceTree = ""; }; 07CEDD802C7DB921003E1885 /* generateDoc.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = generateDoc.sh; path = ../generateDoc.sh; sourceTree = ""; }; 07CF426A2CA30728000BD03E /* TokensPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokensPage.swift; sourceTree = ""; }; 07CF42712CA31AC3000BD03E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -249,6 +257,7 @@ 073543192CA17388001187EA /* Typography */ = { isa = PBXGroup; children = ( + 0784B2742CCBD9A900299C10 /* NamedTypography */, 073543172CA172CA001187EA /* TypographyTokenElement.swift */, 0735431A2CA18C48001187EA /* TypographyTokenPage.swift */, ); @@ -285,6 +294,7 @@ 075114DA2CB7D28D00B8B759 /* Size */ = { isa = PBXGroup; children = ( + 0784B2702CCB86C500299C10 /* NamedSize */, 075114D82CB7D28D00B8B759 /* SizeTokenElement.swift */, 075114D92CB7D28D00B8B759 /* SizeTokenPage.swift */, ); @@ -347,6 +357,24 @@ path = Dimension; sourceTree = ""; }; + 0784B2702CCB86C500299C10 /* NamedSize */ = { + isa = PBXGroup; + children = ( + 0784B26F2CCB86C500299C10 /* NamedSize+IconWithTypography.swift */, + 0784B2722CCB8CC800299C10 /* NamedSize+IconDecorative.swift */, + ); + path = NamedSize; + sourceTree = ""; + }; + 0784B2742CCBD9A900299C10 /* NamedTypography */ = { + isa = PBXGroup; + children = ( + 0784B2772CCBDD8900299C10 /* NamedTypography+Illustration.swift */, + 0784B2752CCBD9C300299C10 /* NamedTypography.swift */, + ); + path = NamedTypography; + sourceTree = ""; + }; 07CF42752CA3F461000BD03E /* Elevation */ = { isa = PBXGroup; children = ( @@ -793,6 +821,7 @@ 51087A7B2C46DF9F00160CCF /* Bundle+extension.swift in Sources */, 0765B4962CC159F600E69359 /* NamedColor+Action.swift in Sources */, 0765B4A22CC15C0500E69359 /* NamedColor+OnContent.swift in Sources */, + 0784B2782CCBDD8900299C10 /* NamedTypography+Illustration.swift in Sources */, 077CCE572CB426090059CC28 /* SpaceTokenElement.swift in Sources */, 0735431B2CA18C48001187EA /* TypographyTokenPage.swift in Sources */, 07F75A412CC653EB0004F1AD /* NameSpace+GapStack.swift in Sources */, @@ -805,9 +834,12 @@ 0765B4A62CC15C9D00E69359 /* NamedColor.swift in Sources */, 073543112CA154DE001187EA /* Card.swift in Sources */, 51BD76212C466FCF0033365D /* AboutPage.swift in Sources */, + 0784B2732CCB8CC800299C10 /* NamedSize+IconDecorative.swift in Sources */, 51BD762A2C466FCF0033365D /* Showcase.swift in Sources */, 0765B49E2CC15B7E00E69359 /* NamedColor+Decorative.swift in Sources */, 07F75A432CC654050004F1AD /* NameSpace+PaddingStack.swift in Sources */, + 0784B2762CCBD9C300299C10 /* NamedTypography.swift in Sources */, + 0784B2712CCB86C500299C10 /* NamedSize+IconWithTypography.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1156,8 +1188,8 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/pointfreeco/swift-snapshot-testing.git"; requirement = { - kind = upToNextMajorVersion; - minimumVersion = 1.17.5; + kind = exactVersion; + version = 1.17.6; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Showcase/Showcase.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Showcase/Showcase.xcworkspace/xcshareddata/swiftpm/Package.resolved index dfb105775..cd9f08df4 100644 --- a/Showcase/Showcase.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Showcase/Showcase.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,13 +1,13 @@ { - "originHash" : "c48bd6ce1dff61368be114be7113f793bf250d75bd26b7706f31d9a229918712", + "originHash" : "b0e966f4ace0da078a6fcc1dcd094050f4d63b9437f87a3a6b4948c17b90db4e", "pins" : [ { "identity" : "swift-snapshot-testing", "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing.git", "state" : { - "revision" : "7b0bbbae90c41f848f90ac7b4df6c4f50068256d", - "version" : "1.17.5" + "revision" : "42a086182681cf661f5c47c9b7dc3931de18c6d7", + "version" : "1.17.6" } }, { diff --git a/Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconDecorative.swift b/Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconDecorative.swift new file mode 100644 index 000000000..a2516792d --- /dev/null +++ b/Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconDecorative.swift @@ -0,0 +1,46 @@ +// +// Software Name: OUDS iOS +// SPDX-FileCopyrightText: Copyright (c) Orange SA +// SPDX-License-Identifier: MIT +// +// This software is distributed under the MIT license, +// the text of which is available at https://opensource.org/license/MIT/ +// or see the "LICENSE" file for more details. +// +// Authors: See CONTRIBUTORS.txt +// Software description: A SwiftUI components library with code examples for Orange Unified Design System +// + +import OUDS +import OUDSTokensSemantic + +extension NamedSize { + enum IconDecorative: String, CaseIterable { + case sizeIconDecorativeShortest + case sizeIconDecorativeShorter + case sizeIconDecorativeShort + case sizeIconDecorativeMedium + case sizeIconDecorativeTall + case sizeIconDecorativeTaller + case sizeIconDecorativeTallest + + func token(from theme: OUDSTheme) -> SizeSemanticToken { + switch self { + case .sizeIconDecorativeShortest: + return theme.sizeIconDecorativeShortest + case .sizeIconDecorativeShorter: + return theme.sizeIconDecorativeShorter + case .sizeIconDecorativeShort: + return theme.sizeIconDecorativeShort + case .sizeIconDecorativeMedium: + return theme.sizeIconDecorativeMedium + case .sizeIconDecorativeTall: + return theme.sizeIconDecorativeTall + case .sizeIconDecorativeTaller: + return theme.sizeIconDecorativeTaller + case .sizeIconDecorativeTallest: + return theme.sizeIconDecorativeTallest + } + } + } +} diff --git a/Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconWithTypography.swift b/Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconWithTypography.swift new file mode 100644 index 000000000..fe54c55ce --- /dev/null +++ b/Showcase/Showcase/Pages/Tokens/Dimension/Size/NamedSize/NamedSize+IconWithTypography.swift @@ -0,0 +1,209 @@ +// +// Software Name: OUDS iOS +// SPDX-FileCopyrightText: Copyright (c) Orange SA +// SPDX-License-Identifier: MIT +// +// This software is distributed under the MIT license, +// the text of which is available at https://opensource.org/license/MIT/ +// or see the "LICENSE" file for more details. +// +// Authors: See CONTRIBUTORS.txt +// Software description: A SwiftUI components library with code examples for Orange Unified Design System +// + +import OUDS +import OUDSTokensSemantic +import SwiftUICore + +extension NamedSize { + + enum IconWithTypography: String, CaseIterable { + case sizeIconWithHeadingXLargeShort + case sizeIconWithHeadingXLargeMedium + case sizeIconWithHeadingXLargeTall + case sizeIconWithHeadingLargeShort + case sizeIconWithHeadingLargeMedium + case sizeIconWithHeadingLargeTall + case sizeIconWithHeadingMediumShort + case sizeIconWithHeadingMediumMedium + case sizeIconWithHeadingMediumTall + case sizeIconWithHeadingSmallShort + case sizeIconWithHeadingSmallMedium + case sizeIconWithHeadingSmallTall + case sizeIconWithBodyLargeShort + case sizeIconWithBodyLargeMedium + case sizeIconWithBodyLargeTall + case sizeIconWithBodyMediumShort + case sizeIconWithBodyMediumMedium + case sizeIconWithBodyMediumTall + case sizeIconWithBodySmallShort + case sizeIconWithBodySmallMedium + case sizeIconWithBodySmallTall + case sizeIconWithLabelXLargeSizeShort + case sizeIconWithLabelXLargeSizeMedium + case sizeIconWithLabelXLargeSizeTall + case sizeIconWithLabelLargeSizeShorter + case sizeIconWithLabelLargeSizeShort + case sizeIconWithLabelLargeSizeMedium + case sizeIconWithLabelLargeSizeTall + case sizeIconWithLabelLargeSizeTaller + case sizeIconWithLabelMediumSizeShort + case sizeIconWithLabelMediumSizeMedium + case sizeIconWithLabelMediumSizeTall + case sizeIconWithLabelSmallSizeShort + case sizeIconWithLabelSmallSizeMedium + case sizeIconWithLabelSmallSizeTall + + var namedTypography: NamedTypography { + switch self { + case .sizeIconWithHeadingXLargeShort: + return .headingXLarge + case .sizeIconWithHeadingXLargeMedium: + return .headingXLarge + case .sizeIconWithHeadingXLargeTall: + return .headingXLarge + case .sizeIconWithHeadingLargeShort: + return .headingLarge + case .sizeIconWithHeadingLargeMedium: + return .headingLarge + case .sizeIconWithHeadingLargeTall: + return .headingLarge + case .sizeIconWithHeadingMediumShort: + return .headingMedium + case .sizeIconWithHeadingMediumMedium: + return .headingMedium + case .sizeIconWithHeadingMediumTall: + return .headingMedium + case .sizeIconWithHeadingSmallShort: + return .headingSmall + case .sizeIconWithHeadingSmallMedium: + return .headingSmall + case .sizeIconWithHeadingSmallTall: + return .headingSmall + case .sizeIconWithBodyLargeShort: + return .bodyDefaultLarge + case .sizeIconWithBodyLargeMedium: + return .bodyDefaultLarge + case .sizeIconWithBodyLargeTall: + return .bodyDefaultLarge + case .sizeIconWithBodyMediumShort: + return .bodyDefaultMedium + case .sizeIconWithBodyMediumMedium: + return .bodyDefaultMedium + case .sizeIconWithBodyMediumTall: + return .bodyDefaultMedium + case .sizeIconWithBodySmallShort: + return .bodyDefaultSmall + case .sizeIconWithBodySmallMedium: + return .bodyDefaultSmall + case .sizeIconWithBodySmallTall: + return .bodyDefaultSmall + case .sizeIconWithLabelXLargeSizeShort: + return .labelDefaultXLarge + case .sizeIconWithLabelXLargeSizeMedium: + return .labelDefaultXLarge + case .sizeIconWithLabelXLargeSizeTall: + return .labelDefaultXLarge + case .sizeIconWithLabelLargeSizeShorter: + return .labelDefaultXLarge + case .sizeIconWithLabelLargeSizeShort: + return .labelDefaultLarge + case .sizeIconWithLabelLargeSizeMedium: + return .labelDefaultLarge + case .sizeIconWithLabelLargeSizeTall: + return .labelDefaultLarge + case .sizeIconWithLabelLargeSizeTaller: + return .labelDefaultLarge + case .sizeIconWithLabelMediumSizeShort: + return .labelDefaultMedium + case .sizeIconWithLabelMediumSizeMedium: + return .labelDefaultMedium + case .sizeIconWithLabelMediumSizeTall: + return .labelDefaultMedium + case .sizeIconWithLabelSmallSizeShort: + return .labelDefaultSmall + case .sizeIconWithLabelSmallSizeMedium: + return .labelDefaultSmall + case .sizeIconWithLabelSmallSizeTall: + return .labelDefaultSmall + } + } + + // swiftlint:disable function_body_length + func token(fot theme: OUDSTheme, userInterfaceSizeClass: UserInterfaceSizeClass) -> SizeSemanticToken { + switch self { + case .sizeIconWithHeadingXLargeShort: + return theme.sizeIconWithHeadingXLargeShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingXLargeMedium: + return theme.sizeIconWithHeadingXLargeMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingXLargeTall: + return theme.sizeIconWithHeadingXLargeTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingLargeShort: + return theme.sizeIconWithHeadingLargeShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingLargeMedium: + return theme.sizeIconWithHeadingLargeMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingLargeTall: + return theme.sizeIconWithHeadingLargeTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingMediumShort: + return theme.sizeIconWithHeadingMediumShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingMediumMedium: + return theme.sizeIconWithHeadingMediumMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingMediumTall: + return theme.sizeIconWithHeadingMediumTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingSmallShort: + return theme.sizeIconWithHeadingSmallShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingSmallMedium: + return theme.sizeIconWithHeadingSmallMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithHeadingSmallTall: + return theme.sizeIconWithHeadingSmallTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodyLargeShort: + return theme.sizeIconWithBodyLargeShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodyLargeMedium: + return theme.sizeIconWithBodyLargeMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodyLargeTall: + return theme.sizeIconWithBodyLargeTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodyMediumShort: + return theme.sizeIconWithBodyMediumShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodyMediumMedium: + return theme.sizeIconWithBodyMediumMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodyMediumTall: + return theme.sizeIconWithBodyMediumTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodySmallShort: + return theme.sizeIconWithBodySmallShort.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodySmallMedium: + return theme.sizeIconWithBodySmallMedium.dimension(for: userInterfaceSizeClass) + case .sizeIconWithBodySmallTall: + return theme.sizeIconWithBodySmallTall.dimension(for: userInterfaceSizeClass) + case .sizeIconWithLabelXLargeSizeShort: + return theme.sizeIconWithLabelXLargeSizeShort + case .sizeIconWithLabelXLargeSizeMedium: + return theme.sizeIconWithLabelXLargeSizeMedium + case .sizeIconWithLabelXLargeSizeTall: + return theme.sizeIconWithLabelXLargeSizeTall + case .sizeIconWithLabelLargeSizeShorter: + return theme.sizeIconWithLabelLargeSizeShorter + case .sizeIconWithLabelLargeSizeShort: + return theme.sizeIconWithLabelLargeSizeShort + case .sizeIconWithLabelLargeSizeMedium: + return theme.sizeIconWithLabelLargeSizeMedium + case .sizeIconWithLabelLargeSizeTall: + return theme.sizeIconWithLabelLargeSizeTall + case .sizeIconWithLabelLargeSizeTaller: + return theme.sizeIconWithLabelLargeSizeTaller + case .sizeIconWithLabelMediumSizeShort: + return theme.sizeIconWithLabelMediumSizeShort + case .sizeIconWithLabelMediumSizeMedium: + return theme.sizeIconWithLabelMediumSizeMedium + case .sizeIconWithLabelMediumSizeTall: + return theme.sizeIconWithLabelMediumSizeTall + case .sizeIconWithLabelSmallSizeShort: + return theme.sizeIconWithLabelSmallSizeShort + case .sizeIconWithLabelSmallSizeMedium: + return theme.sizeIconWithLabelSmallSizeMedium + case .sizeIconWithLabelSmallSizeTall: + return theme.sizeIconWithLabelSmallSizeTall + } + } + // swiftlint:enable function_body_length + } +} diff --git a/Showcase/Showcase/Pages/Tokens/Dimension/Size/SizeTokenPage.swift b/Showcase/Showcase/Pages/Tokens/Dimension/Size/SizeTokenPage.swift index dad4dd435..5877029bd 100644 --- a/Showcase/Showcase/Pages/Tokens/Dimension/Size/SizeTokenPage.swift +++ b/Showcase/Showcase/Pages/Tokens/Dimension/Size/SizeTokenPage.swift @@ -19,26 +19,33 @@ struct SizeTokenPage: View { @Environment(\.theme) private var theme @Environment(\.horizontalSizeClass) private var horizontalSizeClass - @Environment(\.verticalSizeClass) private var verticalSizeClass @Environment(\.colorScheme) private var colorScheme // MARK: Body var body: some View { - VStack(alignment: .leading, spacing: theme.spaceFixedNone) { - ForEach(NamedSizing.allCases, id: \.rawValue) { sizingName in - illustration(for: sizingName) + Group { + Section { illustrationForIconDecorative() } header: { + header("app_tokens_dimension_size_iconDecorative_label") + } + Section { illustrationIconWithLabel() } header: { + header("app_tokens_dimension_size_iconWithLabel_label") } } - .frame(maxWidth: .infinity) .padding(.horizontal, theme.spaceFixedMedium) } - // MARK: Private helpers + // MARK: Illustration icon decorative - private func illustration(for namedSizing: NamedSizing) -> some View { - let token = namedSizing.token(from: theme) - let name = namedSizing.rawValue + private func illustrationForIconDecorative() -> some View { + ForEach(NamedSize.IconDecorative.allCases, id: \.rawValue) { namedSize in + illustrationIconDecorative(for: namedSize) + } + } + + private func illustrationIconDecorative(for namedSize: NamedSize.IconDecorative) -> some View { + let token = namedSize.token(from: theme) + let name = namedSize.rawValue let value = String(format: "(%.0f) pt", token) return ShowcaseTokenIllustration(tokenName: name, tokenValue: value) { @@ -50,41 +57,52 @@ struct SizeTokenPage: View { Image("ic_token") .resizable() .renderingMode(.template) - .foregroundColor(.blue) + .foregroundColor(theme.colorAlwaysInfo.color(for: colorScheme)) .frame(width: token, height: token, alignment: .center) .accessibilityHidden(true) } } } -} -// MARK: - Named Spacing - -private enum NamedSizing: String, CaseIterable { - case sizeIconDecorativeShortest - case sizeIconDecorativeShorter - case sizeIconDecorativeShort - case sizeIconDecorativeMedium - case sizeIconDecorativeTall - case sizeIconDecorativeTaller - case sizeIconDecorativeTallest - - func token(from theme: OUDSTheme) -> SizeSemanticToken { - switch self { - case .sizeIconDecorativeShortest: - return theme.sizeIconDecorativeShortest - case .sizeIconDecorativeShorter: - return theme.sizeIconDecorativeShorter - case .sizeIconDecorativeShort: - return theme.sizeIconDecorativeShort - case .sizeIconDecorativeMedium: - return theme.sizeIconDecorativeMedium - case .sizeIconDecorativeTall: - return theme.sizeIconDecorativeTall - case .sizeIconDecorativeTaller: - return theme.sizeIconDecorativeTaller - case .sizeIconDecorativeTallest: - return theme.sizeIconDecorativeTallest + // MARK: Illustration icon with label + + private func illustrationIconWithLabel() -> some View { + ForEach(NamedSize.IconWithTypography.allCases, id: \.rawValue) { namedIconSize in + illustrationIconWithLabel(for: namedIconSize) } } + + @ViewBuilder + private func illustrationIconWithLabel(for namedSize: NamedSize.IconWithTypography) -> some View { + let token = namedSize.token(fot: theme, userInterfaceSizeClass: horizontalSizeClass ?? .regular) + let namedTypography = namedSize.namedTypography + let value = String(format: "\(namedSize.rawValue) (%.0f) pt", token) + + HStack { + Image("ic_token") + .resizable() + .renderingMode(.template) + .foregroundColor(theme.colorAlwaysInfo.color(for: colorScheme)) + .frame(width: token, height: token, alignment: .center) + .accessibilityHidden(true) + + VStack(alignment: .leading) { + illustration(for: namedTypography, in: theme) + .foregroundStyle(theme.colorContentDefault.color(for: colorScheme)) + Text(value) + .typeBodyDefaultMedium(theme) + .foregroundStyle(theme.colorContentMuted.color(for: colorScheme)) + } + } + } + + // MARK: Common helpers + + private func header(_ text: LocalizedStringKey) -> some View { + Text(text).showcaseSectionHeaderStyle() + } } + +// MARK: - Named Size + +enum NamedSize { } diff --git a/Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography+Illustration.swift b/Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography+Illustration.swift new file mode 100644 index 000000000..1323630d9 --- /dev/null +++ b/Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography+Illustration.swift @@ -0,0 +1,82 @@ +// +// Software Name: OUDS iOS +// SPDX-FileCopyrightText: Copyright (c) Orange SA +// SPDX-License-Identifier: MIT +// +// This software is distributed under the MIT license, +// the text of which is available at https://opensource.org/license/MIT/ +// or see the "LICENSE" file for more details. +// +// Authors: See CONTRIBUTORS.txt +// Software description: A SwiftUI components library with code examples for Orange Unified Design System +// + +import OUDS +import OUDSTokensSemantic +import SwiftUI + +// MARK: - Token Illustration + +// Used in Typography screen and SizeIconWithLabel +extension View { + + @ViewBuilder + func illustration(for namedTypography: NamedTypography, in theme: OUDSTheme) -> some View { + switch namedTypography { + case .displayLarge: + Text(namedTypography.rawValue.camelCase).typeDisplayLarge(theme) + case .displayMedium: + Text(namedTypography.rawValue.camelCase).typeDisplayMedium(theme) + case .displaySmall: + Text(namedTypography.rawValue.camelCase).typeDisplaySmall(theme) + case .headingXLarge: + Text(namedTypography.rawValue.camelCase).typeHeadingXLarge(theme) + case .headingLarge: + Text(namedTypography.rawValue.camelCase).typeHeadingLarge(theme) + case .headingMedium: + Text(namedTypography.rawValue.camelCase).typeHeadingMedium(theme) + case .headingSmall: + Text(namedTypography.rawValue.camelCase).typeHeadingSmall(theme) + case .bodyDefaultLarge: + Text(namedTypography.rawValue.camelCase).typeBodyDefaultLarge(theme) + case .bodyDefaultMedium: + Text(namedTypography.rawValue.camelCase).typeBodyDefaultMedium(theme) + case .bodyDefaultSmall: + Text(namedTypography.rawValue.camelCase).typeBodyDefaultSmall(theme) + case .bodyStrongLarge: + Text(namedTypography.rawValue.camelCase).typeBodyStrongLarge(theme) + case .bodyStrongMedium: + Text(namedTypography.rawValue.camelCase).typeBodyStrongMedium(theme) + case .bodyStrongSmall: + Text(namedTypography.rawValue.camelCase).typeBodyStrongSmall(theme) + case .labelDefaultXLarge: + Text(namedTypography.rawValue.camelCase).typeLabelDefaultXLarge(theme) + case .labelDefaultLarge: + Text(namedTypography.rawValue.camelCase).typeLabelDefaultLarge(theme) + case .labelDefaultMedium: + Text(namedTypography.rawValue.camelCase).typeLabelDefaultMedium(theme) + case .labelDefaultSmall: + Text(namedTypography.rawValue.camelCase).typeLabelDefaultSmall(theme) + case .labelStrongXLarge: + Text(namedTypography.rawValue.camelCase).typeLabelStrongXLarge(theme) + case .labelStrongLarge: + Text(namedTypography.rawValue.camelCase).typeLabelStrongLarge(theme) + case .labelStrongMedium: + Text(namedTypography.rawValue.camelCase).typeLabelStrongMedium(theme) + case .labelStrongSmall: + Text(namedTypography.rawValue.camelCase).typeLabelStrongSmall(theme) + case .codeSmall: + Text(namedTypography.rawValue.camelCase).typeCodeMedium(theme) + case .codeMedium: + Text(namedTypography.rawValue.camelCase).typeCodeMedium(theme) + } + } +} + +extension String { + // swiftlint:disable strict_fileprivate + fileprivate var camelCase: String { + self.prefix(1).capitalized + self.dropFirst() + } + // swiftlint:enable strict_fileprivate +} diff --git a/Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography.swift b/Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography.swift new file mode 100644 index 000000000..ee97cd0bb --- /dev/null +++ b/Showcase/Showcase/Pages/Tokens/Typography/NamedTypography/NamedTypography.swift @@ -0,0 +1,97 @@ +// +// Software Name: OUDS iOS +// SPDX-FileCopyrightText: Copyright (c) Orange SA +// SPDX-License-Identifier: MIT +// +// This software is distributed under the MIT license, +// the text of which is available at https://opensource.org/license/MIT/ +// or see the "LICENSE" file for more details. +// +// Authors: See CONTRIBUTORS.txt +// Software description: A SwiftUI components library with code examples for Orange Unified Design System +// + +import OUDS +import OUDSTokensSemantic +import SwiftUI + +// MARK: - Named Typography + +enum NamedTypography: String, CaseIterable { + case displayLarge + case displayMedium + case displaySmall + case headingXLarge + case headingLarge + case headingMedium + case headingSmall + case bodyDefaultLarge + case bodyDefaultMedium + case bodyDefaultSmall + case bodyStrongLarge + case bodyStrongMedium + case bodyStrongSmall + case labelDefaultXLarge + case labelDefaultLarge + case labelDefaultMedium + case labelDefaultSmall + case labelStrongXLarge + case labelStrongLarge + case labelStrongMedium + case labelStrongSmall + case codeMedium + case codeSmall + + // MARK: - Token Values + + func token(from theme: OUDSTheme) -> MultipleTypographyTokens { + switch self { + case .displayLarge: + return theme.typeDisplayLarge + case .displayMedium: + return theme.typeDisplayMedium + case .displaySmall: + return theme.typeDisplaySmall + case .headingXLarge: + return theme.typeHeadingXLarge + case .headingLarge: + return theme.typeHeadingLarge + case .headingMedium: + return theme.typeHeadingMedium + case .headingSmall: + return theme.typeHeadingSmall + case .bodyDefaultLarge: + return theme.typeBodyDefaultLarge + case .bodyDefaultMedium: + return theme.typeBodyDefaultMedium + case .bodyDefaultSmall: + return theme.typeBodyDefaultSmall + case .bodyStrongLarge: + return theme.typeBodyStrongLarge + case .bodyStrongMedium: + return theme.typeBodyStrongMedium + case .bodyStrongSmall: + return theme.typeBodyStrongSmall + case .labelDefaultXLarge: + return theme.typeLabelDefaultXLarge + case .labelDefaultLarge: + return theme.typeLabelDefaultLarge + case .labelDefaultMedium: + return theme.typeLabelDefaultMedium + case .labelDefaultSmall: + return theme.typeLabelDefaultSmall + case .labelStrongXLarge: + return theme.typeLabelStrongXLarge + case .labelStrongLarge: + return theme.typeLabelStrongLarge + case .labelStrongMedium: + return theme.typeLabelStrongMedium + case .labelStrongSmall: + return theme.typeLabelStrongSmall + case .codeSmall: + return theme.typeCodeSmall + case .codeMedium: + return theme.typeCodeMedium + } + } +} diff --git a/Showcase/Showcase/Pages/Tokens/Typography/TypographyTokenPage.swift b/Showcase/Showcase/Pages/Tokens/Typography/TypographyTokenPage.swift index a2d185a08..0c74a947e 100644 --- a/Showcase/Showcase/Pages/Tokens/Typography/TypographyTokenPage.swift +++ b/Showcase/Showcase/Pages/Tokens/Typography/TypographyTokenPage.swift @@ -21,6 +21,7 @@ struct TypographyTokenPage: View { @Environment(\.theme) private var theme @Environment(\.colorScheme) private var colorScheme + @Environment(\.horizontalSizeClass) private var horizontalSizeClass // MARK: Body @@ -30,7 +31,6 @@ struct TypographyTokenPage: View { illustration(from: typographyName) } } - .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, theme.spaceFixedMedium) .navigationTitle(LocalizedStringKey("app_tokens_typography_label")) } @@ -39,10 +39,11 @@ struct TypographyTokenPage: View { @ViewBuilder private func illustration(from namedTypography: NamedTypography) -> some View { - let token = namedTypography.token(from: theme).compact + let horizontalSizeClass = horizontalSizeClass ?? .regular + let token = namedTypography.token(from: theme).typographyToken(for: horizontalSizeClass) VStack(alignment: .leading, spacing: theme.spaceFixedNone) { - typgraphyIllustration(from: namedTypography) + illustration(for: namedTypography, in: theme) .foregroundStyle(theme.colorContentDefault.color(for: colorScheme)) Group { @@ -59,141 +60,4 @@ struct TypographyTokenPage: View { .frame(maxWidth: .infinity, alignment: .leading) .padding(.vertical, theme.spaceFixedShorter) } - - @ViewBuilder - private func typgraphyIllustration(from namedTypography: NamedTypography) -> some View { - switch namedTypography { - case .displayLarge: - Text(namedTypography.rawValue.camelCase).typeDisplayLarge(theme) - case .displayMedium: - Text(namedTypography.rawValue.camelCase).typeDisplayMedium(theme) - case .displaySmall: - Text(namedTypography.rawValue.camelCase).typeDisplaySmall(theme) - case .headingXLarge: - Text(namedTypography.rawValue.camelCase).typeHeadingXLarge(theme) - case .headingLarge: - Text(namedTypography.rawValue.camelCase).typeHeadingLarge(theme) - case .headingMedium: - Text(namedTypography.rawValue.camelCase).typeHeadingMedium(theme) - case .headingSmall: - Text(namedTypography.rawValue.camelCase).typeHeadingSmall(theme) - case .bodyDefaultLarge: - Text(namedTypography.rawValue.camelCase).typeBodyDefaultLarge(theme) - case .bodyDefaultMedium: - Text(namedTypography.rawValue.camelCase).typeBodyDefaultMedium(theme) - case .bodyDefaultSmall: - Text(namedTypography.rawValue.camelCase).typeBodyDefaultSmall(theme) - case .bodyStrongLarge: - Text(namedTypography.rawValue.camelCase).typeBodyStrongLarge(theme) - case .bodyStrongMedium: - Text(namedTypography.rawValue.camelCase).typeBodyStrongMedium(theme) - case .bodyStrongSmall: - Text(namedTypography.rawValue.camelCase).typeBodyStrongSmall(theme) - case .labelDefaultXLarge: - Text(namedTypography.rawValue.camelCase).typeLabelDefaultXLarge(theme) - case .labelDefaultLarge: - Text(namedTypography.rawValue.camelCase).typeLabelDefaultLarge(theme) - case .labelDefaultMedium: - Text(namedTypography.rawValue.camelCase).typeLabelDefaultMedium(theme) - case .labelDefaultSmall: - Text(namedTypography.rawValue.camelCase).typeLabelDefaultSmall(theme) - case .labelStrongXLarge: - Text(namedTypography.rawValue.camelCase).typeLabelStrongXLarge(theme) - case .labelStrongLarge: - Text(namedTypography.rawValue.camelCase).typeLabelStrongLarge(theme) - case .labelStrongMedium: - Text(namedTypography.rawValue.camelCase).typeLabelStrongMedium(theme) - case .labelStrongSmall: - Text(namedTypography.rawValue.camelCase).typeLabelStrongSmall(theme) - case .codeSmall: - Text(namedTypography.rawValue.camelCase).typeCodeMedium(theme) - case .codeMedium: - Text(namedTypography.rawValue.camelCase).typeCodeMedium(theme) - } - } -} - -extension String { - var camelCase: String { - self.prefix(1).capitalized + self.dropFirst() - } -} - -// MARK: - Named Typography - -private enum NamedTypography: String, CaseIterable { - case displayLarge - case displayMedium - case displaySmall - case headingXLarge - case headingLarge - case headingMedium - case headingSmall - case bodyDefaultLarge - case bodyDefaultMedium - case bodyDefaultSmall - case bodyStrongLarge - case bodyStrongMedium - case bodyStrongSmall - case labelDefaultXLarge - case labelDefaultLarge - case labelDefaultMedium - case labelDefaultSmall - case labelStrongXLarge - case labelStrongLarge - case labelStrongMedium - case labelStrongSmall - case codeMedium - case codeSmall - - func token(from theme: OUDSTheme) -> MultipleTypographyTokens { - switch self { - case .displayLarge: - return theme.typeDisplayLarge - case .displayMedium: - return theme.typeDisplayMedium - case .displaySmall: - return theme.typeDisplaySmall - case .headingXLarge: - return theme.typeHeadingXLarge - case .headingLarge: - return theme.typeHeadingLarge - case .headingMedium: - return theme.typeHeadingMedium - case .headingSmall: - return theme.typeHeadingSmall - case .bodyDefaultLarge: - return theme.typeBodyDefaultLarge - case .bodyDefaultMedium: - return theme.typeBodyDefaultMedium - case .bodyDefaultSmall: - return theme.typeBodyDefaultSmall - case .bodyStrongLarge: - return theme.typeBodyStrongLarge - case .bodyStrongMedium: - return theme.typeBodyStrongMedium - case .bodyStrongSmall: - return theme.typeBodyStrongSmall - case .labelDefaultXLarge: - return theme.typeLabelDefaultXLarge - case .labelDefaultLarge: - return theme.typeLabelDefaultLarge - case .labelDefaultMedium: - return theme.typeLabelDefaultMedium - case .labelDefaultSmall: - return theme.typeLabelDefaultSmall - case .labelStrongXLarge: - return theme.typeLabelStrongXLarge - case .labelStrongLarge: - return theme.typeLabelStrongLarge - case .labelStrongMedium: - return theme.typeLabelStrongMedium - case .labelStrongSmall: - return theme.typeLabelStrongSmall - case .codeSmall: - return theme.typeCodeSmall - case .codeMedium: - return theme.typeCodeMedium - } - } } diff --git a/Showcase/Showcase/Resources/en.lproj/Localizable.strings b/Showcase/Showcase/Resources/en.lproj/Localizable.strings index 8fb65da79..5143bd35c 100644 --- a/Showcase/Showcase/Resources/en.lproj/Localizable.strings +++ b/Showcase/Showcase/Resources/en.lproj/Localizable.strings @@ -51,6 +51,8 @@ "app_tokens_dimension_size_label" = "Size"; "app_tokens_dimension_size_description_text" = "Size refers to the specific measurements used to define the dimensions of UI elements within the design system."; +"app_tokens_dimension_size_iconWithLabel_label" = "Icon with label"; +"app_tokens_dimension_size_iconDecorative_label" = "Icon decorative"; "app_tokens_elevation_label" = "Elevation"; "app_tokens_elevation_description_text" = "Shadows are used to give the impression of distance or elevation between surfaces, which adds depth to our designs.";