Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#151] Add grid tokens screen in demo app #276

Merged
merged 6 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
pylapp marked this conversation as resolved.
Show resolved Hide resolved
./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 {
pylapp marked this conversation as resolved.
Show resolved Hide resolved
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
Loading