Skip to content

Commit

Permalink
feat: add grid tokens screen in demo app (#151) (#276)
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com>
Co-authored-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com>
Reviewed-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com>
Tested-by: Pierre-Yves Lapersonne <pierreyves.lapersonne@orange.com>
  • Loading branch information
ludovic35 and pylapp authored Nov 14, 2024
1 parent 024eb28 commit 22e215e
Show file tree
Hide file tree
Showing 22 changed files with 448 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- [DemoApp] Add grid tokens screen in demo app ([#151](https://github.com/Orange-OpenSource/ouds-ios/issues/151))
- [Tool] GitHub Action to run SwiftLint for *main* and *develop* branches

### Changed
Expand Down
10 changes: 8 additions & 2 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ Any use or displaying shall constitute an infringement under intellectual proper
./Showcase/Showcase/Resources/Assets.xcassets/ic_info.imageset/ic_info.svg

./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_empty_screen.imageset/il_empty_screen.svg

./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_tokens_grid_column_margin.imageset/il_tokens_grid_column_margin.png
./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_tokens_grid_column_margin.imageset/il_tokens_grid_column_margin_dark.png
./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_tokens_grid_max_width.imageset/il_tokens_grid_max_width.png
./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_tokens_grid_max_width.imageset/il_tokens_grid_max_width_dark.png
./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_tokens_grid_min_width.imageset/il_tokens_grid_min_width.png
./Showcase/Showcase/Resources/Assets.xcassets/Illustrations/il_tokens_grid_min_width.imageset/il_tokens_grid_min_width_dark.png
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_border.imageset/ic_border.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_dimension.imageset/ic_dimension.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_filter_effects.imageset/ic_filter_effects.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_grid.imageset/ic_grid.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_layers.imageset/ic_layers.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_palette.imageset/ic_palette.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_vector.imageset/ic_vector.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_typography.imageset/ic_typography.svg
./Showcase/Showcase/Resources/Assets.xcassets/Tokens/ic_union.imageset/ic_union.svg

End of the parts list under Orange SA Copyright
End of the parts list under Orange SA Copyright
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// 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 OUDSTokensRaw
import OUDSTokensSemantic

extension OUDSTheme {

// MARK: Semantic Grid token - Helper

/// The min column width of a grid.
/// - Parameter sizeClass: The current interface size class
/// - Returns `GridRawToken`: The minimal width according to viewports / size classes.
public final func gridMinWidth(for sizeClass: OUDSUserInterfaceSizeClass) -> GridRawToken {
switch sizeClass {
case .extraCompact:
return gridExtraCompactMinWidth
case .compact:
return gridCompactMinWidth
case .regular:
return gridRegularMinWidth
@unknown default:
fatalError("🤖 Raw token unavailable for \(sizeClass)!")
}
}

/// The max column width of a grid.
/// - Parameter sizeClass: The current interface size class
/// - Returns `GridRawToken`: The maximal width according to viewports / size classes.
public final func gridMaxWidth(for sizeClass: OUDSUserInterfaceSizeClass) -> GridRawToken {
switch sizeClass {
case .extraCompact:
return gridExtraCompactMaxWidth
case .compact:
return gridCompactMaxWidth
case .regular:
return gridRegularMaxWidth
@unknown default:
fatalError("🤖 Raw token unavailable for \(sizeClass)!")
}
}

/// The margin of a grid.
/// - Parameter sizeClass: The current interface size class
/// - Returns `GridRawToken`: The margin according to viewports / size classes.
public final func gridMargin(for sizeClass: OUDSUserInterfaceSizeClass) -> GridRawToken {
switch sizeClass {
case .extraCompact:
return gridExtraCompactMargin
case .compact:
return gridCompactMargin
case .regular:
return gridRegularMargin
@unknown default:
fatalError("🤖 Raw token unavailable for \(sizeClass)!")
}
}

/// The column gap of a grid.
/// - Parameter sizeClass: The current interface size class
/// - Returns `GridRawToken`: The column gap according to viewports / size classes.
public final func gridColumnGap(for sizeClass: OUDSUserInterfaceSizeClass) -> GridRawToken {
switch sizeClass {
case .extraCompact:
return gridExtraCompactColumnGap
case .compact:
return gridCompactColumnGap
case .regular:
return gridRegularColumnGap
@unknown default:
fatalError("🤖 Raw token unavailable for \(sizeClass)!")
}
}

/// The column count of a grid.
/// - Parameter sizeClass: The current interface size class
/// - Returns `GridRawToken`: The column count according to viewports / size classes.
public final func gridColumnCount(for sizeClass: OUDSUserInterfaceSizeClass) -> GridRawToken {
switch sizeClass {
case .extraCompact:
return gridExtraCompactColumnCount
case .compact:
return gridCompactColumnCount
case .regular:
return gridRegularColumnCount
@unknown default:
fatalError("🤖 Raw token unavailable for \(sizeClass)!")
}
}
}
38 changes: 35 additions & 3 deletions OUDS/Core/OUDS/Sources/OUDSTheme/OUDSThemeableView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import SwiftUI

// MARK: - Environment values

private struct ThemeContractEnvironmentKey: EnvironmentKey {
private struct ThemeEnvironmentKey: EnvironmentKey {

static let defaultValue = OUDSTheme()
}
Expand All @@ -26,10 +26,10 @@ extension EnvironmentValues {
/// The `OUDSTheme` instance exposed as en environment values across the library
public var theme: OUDSTheme {
get {
self[ThemeContractEnvironmentKey.self]
self[ThemeEnvironmentKey.self]
}
set {
self[ThemeContractEnvironmentKey.self] = newValue
self[ThemeEnvironmentKey.self] = newValue
}
}
}
Expand Down Expand Up @@ -69,5 +69,37 @@ public struct OUDSThemeableView<Content>: View where Content: View {
public var body: some View {
content()
.environment(\.theme, theme)
.modifier(UserInterfaceSizeClassModifier())
}
}

/// Private modifier used to set in environment the computed orizontal and vertical size classes.
private struct UserInterfaceSizeClassModifier: ViewModifier {

@Environment(\.horizontalSizeClass) private var horizontalSizeClass
@Environment(\.verticalSizeClass) private var verticalSizeClass

/// According to Apple guidelines, this value of 390 is the limit defining extract compact size classes if lower and compact if higher or equal
private static let extraCompactMaxWidth = 390.0

private var horizontalUserInterfaceSizeClass: OUDSUserInterfaceSizeClass {
if UIScreen.main.bounds.width < Self.extraCompactMaxWidth {
return .extraCompact
} else {
return horizontalSizeClass == .compact ? .compact : .regular
}
}
private var verticalUserInterfaceSizeClass: OUDSUserInterfaceSizeClass {
if UIScreen.main.bounds.width < Self.extraCompactMaxWidth {
return .extraCompact
} else {
return verticalSizeClass == .compact ? .compact : .regular
}
}

func body(content: Content) -> some View {
content
.environment(\.oudsHorizontalSizeClass, horizontalUserInterfaceSizeClass)
.environment(\.oudsVerticalSizeClass, verticalUserInterfaceSizeClass)
}
}
76 changes: 76 additions & 0 deletions OUDS/Core/OUDS/Sources/OUDSUserInterfaceSizeClass.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// 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 SwiftUICore
import UIKit

// MARK: - Environment values

private struct HorizontalSizeClassEnvironmentKey: EnvironmentKey {

static let defaultValue = OUDSUserInterfaceSizeClass.regular
}

private struct VerticalSizeClassEnvironmentKey: EnvironmentKey {

static let defaultValue = OUDSUserInterfaceSizeClass.regular
}

extension EnvironmentValues {

/// The `OUDSUserInterfaceSizeClass` instance exposed as en environment values across the library for the horizontal viewport.
///
/// You receive a ``OUDSUserInterfaceSizeClass`` value when you read this environment value.
/// The value tells you about the amount of horizontal space available to the view that reads it.
/// You can read this size class like any other of the ``EnvironmentValues``, by creating a property with the ``Environment`` property wrapper:
///
/// @Environment(\.oudsHorizontalSizeClass) private var horizontalSizeClass
///
public var oudsHorizontalSizeClass: OUDSUserInterfaceSizeClass {
get {
self[HorizontalSizeClassEnvironmentKey.self]
}
set {
self[HorizontalSizeClassEnvironmentKey.self] = newValue
}
}

/// The `OUDSUserInterfaceSizeClass` instance exposed as en environment values across the library for the vertical viewport.
///
/// You receive a ``OUDSUserInterfaceSizeClass`` value when you read this environment value.
/// The value tells you about the amount of vertical space available to the view that reads it.
/// You can read this size class like any other of the ``EnvironmentValues``, by creating a property with the ``Environment`` property wrapper:
///
/// @Environment(\.oudsVerticalSizeClass) private var verticalSizeClass
///
public var oudsVerticalSizeClass: OUDSUserInterfaceSizeClass {
get {
self[VerticalSizeClassEnvironmentKey.self]
}
set {
self[VerticalSizeClassEnvironmentKey.self] = newValue
}
}
}

/// Enumerates the size classes defined by the design system.
/// The __extraCompact__ size class if for screens with width < 389.
/// The __compact__ and __regular__ size classes are the standard Apple classes.
///
/// See: https://developer.apple.com/design/human-interface-guidelines/layout#iOS-iPadOS-device-size-classes
/// Remark: This enum is defined as a string to easily display its raw value.
public enum OUDSUserInterfaceSizeClass: String, Sendable {
case extraCompact = "Extra Compact"
case compact = "Compact"
case regular = "Regular"
}
16 changes: 16 additions & 0 deletions Showcase/Showcase.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
070C35622C75EB1C0029C6A8 /* OUDS in Frameworks */ = {isa = PBXBuildFile; productRef = 070C35612C75EB1C0029C6A8 /* OUDS */; };
070C35642C773A0D0029C6A8 /* OUDSThemesInverse in Frameworks */ = {isa = PBXBuildFile; productRef = 070C35632C773A0D0029C6A8 /* OUDSThemesInverse */; };
070C35662C7762B90029C6A8 /* OUDSModules in Frameworks */ = {isa = PBXBuildFile; productRef = 070C35652C7762B90029C6A8 /* OUDSModules */; };
070DF8B12CDD07F20043D558 /* GrisTokenPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070DF8AF2CDD07F20043D558 /* GrisTokenPage.swift */; };
070DF8B22CDD07F20043D558 /* GridTokenElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 070DF8AE2CDD07F20043D558 /* GridTokenElement.swift */; };
073543112CA154DE001187EA /* Card.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073543102CA154DE001187EA /* Card.swift */; };
073543132CA1676C001187EA /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 073543122CA1676C001187EA /* Colors.xcassets */; };
073543162CA17275001187EA /* ShowcaseElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 073543152CA17275001187EA /* ShowcaseElement.swift */; };
Expand Down Expand Up @@ -120,6 +122,8 @@
/* Begin PBXFileReference section */
0707B6402C2C3C0400A911E7 /* .github */ = {isa = PBXFileReference; lastKnownFileType = folder; name = .github; path = ../.github; sourceTree = "<group>"; };
0707B6432C2C569500A911E7 /* Gemfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Gemfile; path = ../Gemfile; sourceTree = "<group>"; };
070DF8AE2CDD07F20043D558 /* GridTokenElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridTokenElement.swift; sourceTree = "<group>"; };
070DF8AF2CDD07F20043D558 /* GrisTokenPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GrisTokenPage.swift; sourceTree = "<group>"; };
073543102CA154DE001187EA /* Card.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Card.swift; sourceTree = "<group>"; };
073543122CA1676C001187EA /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
073543152CA17275001187EA /* ShowcaseElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowcaseElement.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -249,6 +253,15 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
070DF8B02CDD07F20043D558 /* Grid */ = {
isa = PBXGroup;
children = (
070DF8AE2CDD07F20043D558 /* GridTokenElement.swift */,
070DF8AF2CDD07F20043D558 /* GrisTokenPage.swift */,
);
path = Grid;
sourceTree = "<group>";
};
0735430F2CA15440001187EA /* Cards */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -523,6 +536,7 @@
075114DD2CB7FD7E00B8B759 /* Color */,
077CCE562CB426090059CC28 /* Dimension */,
07CF42752CA3F461000BD03E /* Elevation */,
070DF8B02CDD07F20043D558 /* Grid */,
07CF427C2CA412F5000BD03E /* Opacity */,
073543192CA17388001187EA /* Typography */,
073543222CA192F9001187EA /* TokenElement.swift */,
Expand Down Expand Up @@ -858,6 +872,8 @@
07F7533B2CC785620007450D /* ShowcaseSectionHeaderStyle.swift in Sources */,
073543182CA172CA001187EA /* TypographyTokenElement.swift in Sources */,
077CCE5C2CB431C50059CC28 /* ShowcaseVariantElement.swift in Sources */,
070DF8B12CDD07F20043D558 /* GrisTokenPage.swift in Sources */,
070DF8B22CDD07F20043D558 /* GridTokenElement.swift in Sources */,
077CCE582CB426090059CC28 /* SpaceTokenPage.swift in Sources */,
07F75A3F2CC653CD0004F1AD /* NameSpace+GapInline.swift in Sources */,
51BD76292C466FCF0033365D /* WebView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "ce9d2b5fcd836ee7f16c345c970c6dad8b1405cc6afc0904bafd4a5916517710",
"originHash" : "37157bb82d55cf8fef2178d1e02e303f55f01b545bfb15038a1dd61301498d2b",
"pins" : [
{
"identity" : "accessibility-statement-lib-ios",
Expand Down
28 changes: 28 additions & 0 deletions Showcase/Showcase/Pages/Tokens/Grid/GridTokenElement.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// 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 SwiftUI

struct GridTokenElement: TokenElement {
let name: String
let imageName: String
let description: String
let pageDescription: AnyView

init() {
name = "app_tokens_grid_label"
imageName = "ic_grid"
description = "app_tokens_grid_description_text"
pageDescription = AnyView(GridTokenPage())
}
}
Loading

0 comments on commit 22e215e

Please sign in to comment.