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

[#405] Add switch component #439

Draft
wants to merge 13 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 10 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 @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- [DesignToolbox] Add text field in component configuration to customize text ([#436](https://github.com/Orange-OpenSource/ouds-ios/issues/436))
- [Library] Switch component ([#405](https://github.com/Orange-OpenSource/ouds-ios/issues/405))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je mettrais cette ligne en haut, avant celle relative à la carte n°436

- [Library] Link component ([#400](https://github.com/Orange-OpenSource/ouds-ios/issues/400))

## [0.10.0](https://github.com/Orange-OpenSource/ouds-ios/compare/0.9.0...0.10.0) - 2025-01-30
Expand Down
36 changes: 34 additions & 2 deletions DesignToolbox/DesignToolbox.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,19 @@
0765B4A02CC15BBC00E69359 /* NamedColor+Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0765B49F2CC15BBC00E69359 /* NamedColor+Content.swift */; };
0765B4A42CC15C3E00E69359 /* NamedColor+Chart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0765B4A32CC15C3E00E69359 /* NamedColor+Chart.swift */; };
0765B4A62CC15C9D00E69359 /* NamedColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0765B4A52CC15C9D00E69359 /* NamedColor.swift */; };
0771A06A2D50FD9D0050FF31 /* SwitchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0771A0682D50FD9D0050FF31 /* SwitchPage.swift */; };
0771A06B2D50FD9D0050FF31 /* SwitchConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0771A0662D50FD9D0050FF31 /* SwitchConfiguration.swift */; };
0771A06C2D50FD9D0050FF31 /* SwitchElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0771A0672D50FD9D0050FF31 /* SwitchElement.swift */; };
0771A06D2D50FD9D0050FF31 /* SwitchPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0771A0682D50FD9D0050FF31 /* SwitchPage.swift */; };
0771A06E2D50FD9D0050FF31 /* SwitchConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0771A0662D50FD9D0050FF31 /* SwitchConfiguration.swift */; };
0771A06F2D50FD9D0050FF31 /* SwitchElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0771A0672D50FD9D0050FF31 /* SwitchElement.swift */; };
077CCE572CB426090059CC28 /* SpaceTokenElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077CCE512CB426090059CC28 /* SpaceTokenElement.swift */; };
077CCE582CB426090059CC28 /* SpaceTokenPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077CCE522CB426090059CC28 /* SpaceTokenPage.swift */; };
077CCE592CB426090059CC28 /* DimensionTokenElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 077CCE542CB426090059CC28 /* DimensionTokenElement.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 */; };
079475A32D5103B30081980A /* DesignToolboxBackgroundModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 079475A22D5103B30081980A /* DesignToolboxBackgroundModifier.swift */; };
079475A42D5103B30081980A /* DesignToolboxBackgroundModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 079475A22D5103B30081980A /* DesignToolboxBackgroundModifier.swift */; };
07AB45872D4D08080001D237 /* DesignToolboxChoicePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07AB45862D4D08080001D237 /* DesignToolboxChoicePicker.swift */; };
07AB45882D4D08080001D237 /* DesignToolboxChoicePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07AB45862D4D08080001D237 /* DesignToolboxChoicePicker.swift */; };
07AB458A2D50CB9B0001D237 /* DesignToolboxTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07AB45892D50CB9B0001D237 /* DesignToolboxTextField.swift */; };
Expand Down Expand Up @@ -252,12 +260,16 @@
0765B49F2CC15BBC00E69359 /* NamedColor+Content.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedColor+Content.swift"; sourceTree = "<group>"; };
0765B4A32CC15C3E00E69359 /* NamedColor+Chart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedColor+Chart.swift"; sourceTree = "<group>"; };
0765B4A52CC15C9D00E69359 /* NamedColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NamedColor.swift; sourceTree = "<group>"; };
0771A0662D50FD9D0050FF31 /* SwitchConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchConfiguration.swift; sourceTree = "<group>"; };
0771A0672D50FD9D0050FF31 /* SwitchElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchElement.swift; sourceTree = "<group>"; };
0771A0682D50FD9D0050FF31 /* SwitchPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchPage.swift; sourceTree = "<group>"; };
077CCE512CB426090059CC28 /* SpaceTokenElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpaceTokenElement.swift; sourceTree = "<group>"; };
077CCE522CB426090059CC28 /* SpaceTokenPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpaceTokenPage.swift; sourceTree = "<group>"; };
077CCE542CB426090059CC28 /* DimensionTokenElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DimensionTokenElement.swift; sourceTree = "<group>"; };
077CCE5B2CB431C50059CC28 /* DesignToolboxVariantElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesignToolboxVariantElement.swift; sourceTree = "<group>"; };
0784B26F2CCB86C500299C10 /* NamedSize+IconWithTypography.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedSize+IconWithTypography.swift"; sourceTree = "<group>"; };
0784B2722CCB8CC800299C10 /* NamedSize+IconDecorative.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NamedSize+IconDecorative.swift"; sourceTree = "<group>"; };
079475A22D5103B30081980A /* DesignToolboxBackgroundModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesignToolboxBackgroundModifier.swift; sourceTree = "<group>"; };
07AB45862D4D08080001D237 /* DesignToolboxChoicePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesignToolboxChoicePicker.swift; sourceTree = "<group>"; };
07AB45892D50CB9B0001D237 /* DesignToolboxTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesignToolboxTextField.swift; sourceTree = "<group>"; };
07B3CCAE2D40E34700DBB10A /* LinkConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkConfiguration.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -411,6 +423,7 @@
073543142CA17244001187EA /* Utils */ = {
isa = PBXGroup;
children = (
079475A22D5103B30081980A /* DesignToolboxBackgroundModifier.swift */,
0735430F2CA15440001187EA /* Cards */,
0708222D2CFF617000570EC7 /* Elements */,
07F7533A2CC785620007450D /* DesignToolboxSectionHeaderStyle.swift */,
Expand Down Expand Up @@ -508,6 +521,16 @@
path = NamedColor;
sourceTree = "<group>";
};
0771A0692D50FD9D0050FF31 /* Switch */ = {
isa = PBXGroup;
children = (
0771A0662D50FD9D0050FF31 /* SwitchConfiguration.swift */,
0771A0672D50FD9D0050FF31 /* SwitchElement.swift */,
0771A0682D50FD9D0050FF31 /* SwitchPage.swift */,
);
path = Switch;
sourceTree = "<group>";
};
077CCE532CB426090059CC28 /* Space */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -786,10 +809,11 @@
51BD760E2C466FCF0033365D /* Components */ = {
isa = PBXGroup;
children = (
07B3CCAD2D40E14C00DBB10A /* Link */,
07F0AFE62CFE055300D334DD /* Utils */,
072141182D02F52A00B7B9C6 /* Button */,
07F0AFD52CFDAD9200D334DD /* EmptyState */,
07B3CCAD2D40E14C00DBB10A /* Link */,
0771A0692D50FD9D0050FF31 /* Switch */,
07F0AFE62CFE055300D334DD /* Utils */,
07F0AFDD2CFDD1FD00D334DD /* ComponentsPage.swift */,
);
path = Components;
Expand Down Expand Up @@ -1142,10 +1166,14 @@
0721411B2D02F52A00B7B9C6 /* ButtonElement.swift in Sources */,
6DB260E12CD0F0520091F72E /* NameSpace+PaddingInset.swift in Sources */,
51952A752D3F9D850068B807 /* DesignToolboxTokenIllustrationBackground.swift in Sources */,
0771A06D2D50FD9D0050FF31 /* SwitchPage.swift in Sources */,
0771A06E2D50FD9D0050FF31 /* SwitchConfiguration.swift in Sources */,
0771A06F2D50FD9D0050FF31 /* SwitchElement.swift in Sources */,
6DB260E22CD0F0520091F72E /* NameSpace+PaddingStack.swift in Sources */,
6DB260E32CD0F0520091F72E /* NameSpace+GapInline.swift in Sources */,
6DB260E42CD0F0520091F72E /* NameSpace+GapStack.swift in Sources */,
6DB260DD2CD0F01F0091F72E /* NamedSpace+Scaled.swift in Sources */,
079475A42D5103B30081980A /* DesignToolboxBackgroundModifier.swift in Sources */,
6DB260DC2CD0F0000091F72E /* DesignToolboxSectionHeaderStyle.swift in Sources */,
6DB260DB2CD0EFD90091F72E /* NamedSize+IconWithTypography.swift in Sources */,
6DB260DA2CD0EF9D0091F72E /* NamedSize+IconDecorative.swift in Sources */,
Expand Down Expand Up @@ -1208,10 +1236,14 @@
075114DC2CB7D28D00B8B759 /* SizeTokenPage.swift in Sources */,
07F0AFD72CFDB3CC00D334DD /* ComponentPage.swift in Sources */,
077CCE592CB426090059CC28 /* DimensionTokenElement.swift in Sources */,
079475A32D5103B30081980A /* DesignToolboxBackgroundModifier.swift in Sources */,
07CF42852CA45DA9000BD03E /* BorderTokenPage.swift in Sources */,
51952A722D3F9D720068B807 /* DesignToolboxTokenIllustration.swift in Sources */,
0765B4982CC15A4000E69359 /* NamedColor+Always.swift in Sources */,
07F75A392CC6462D0004F1AD /* NamedSpace+Fixed.swift in Sources */,
0771A06A2D50FD9D0050FF31 /* SwitchPage.swift in Sources */,
0771A06B2D50FD9D0050FF31 /* SwitchConfiguration.swift in Sources */,
0771A06C2D50FD9D0050FF31 /* SwitchElement.swift in Sources */,
07CF42842CA45DA9000BD03E /* BorderTokenElement.swift in Sources */,
07D7E1972D035566006472EB /* ButtonConfiguration.swift in Sources */,
07CF42802CA41325000BD03E /* OpacityTokenPage.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ struct ButtonConfiguration: View {
}

if model.layout == .iconAndText || model.layout == .textOnly {
DesignToolboxTextField(text: $model.text, prompt: "app_component_common_userText_prompt")
DesignToolboxTextField(text: $model.text, prompt: "app_components_common_userText_prompt")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je trouve curieux d'utiliser du camel case en plus du snake case, c'est normal d'avoir "userText" et pas par exemple "user_text" ? Je ne connais pas les règles appliquées au wording ici :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf. règles de naming dans le fichier

}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct ComponentsPage: View {
let componentElements: [DesignToolboxElement] = [
ButtonElement(),
LinkElement(),
SwitchElement(),
]

var body: some View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ struct EmptyState: View {
.frame(width: 160, height: 160, alignment: .center)

VStack(alignment: .center, spacing: theme.spaces.spaceFixedShorter) {
Text("app_component_emptyContent_text")
Text("app_components_emptyContent_text")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem que précédemment, "empty_content" plutôt ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf règles de naming

.typeHeadingMedium(theme)
Text("app_component_emptyContent_description_text")
Text("app_components_emptyContent_description_text")
.typeBodyDefaultSmall(theme)
}
.padding(.vertical, theme.spaces.spaceFixedMedium)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ struct LinkConfiguration: View {
}
}

DesignToolboxTextField(text: $model.text, prompt: "app_component_common_userText_prompt")
DesignToolboxTextField(text: $model.text, prompt: "app_components_common_userText_prompt")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"user_text" plutôt que "userText" ?

}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
//
// 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 OUDSComponents
import SwiftUI

// MARK: - Switch Configuration Model

/// The model shared between `SwitchPageConfiguration` view and `SwitchPageComponent` view.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SwitchPageConfiguration n'existe pas, SwitchPage plutôt ?
De même, SwitchPageComponent n'existe pas.

final class SwitchConfigurationModel: ComponentConfiguration {

// MARK: Published properties

@Published var enabled: Bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tous tes @published sont collés sans saut de ligne ; pour des raisons de clarté il faudrait mettre des sauts de ligne comme d'habitude :)

didSet { updateCode() }
}
@Published var switchOnly: Bool {
didSet { updateCode() }
}
@Published var helperText: Bool {
didSet { updateCode() }
}
@Published var icon: Bool {
didSet { updateCode() }
}
@Published var onError: Bool {
didSet { updateCode() }
}
@Published var divider: Bool {
didSet { updateCode() }
}
@Published var orientation: OUDSSwitch.Orientation {
didSet { updateCode() }
}
@Published var labelContent: String
@Published var helperTextContent: String

// MARK: Initializer

override init() {
enabled = true
switchOnly = false
helperText = true
icon = true
onError = false
divider = true
orientation = .default
labelContent = String(localized: "app_components_switch_label_text")
helperTextContent = String(localized: "app_components_switch_helperText_text")
}

deinit { }

// MARK: Component Configuration

override func updateCode() {
if switchOnly {
code =
"""
OUDSSwitch(isOn: $isOn)
\(disableCode))
"""
} else {
code =
"""
OUDSSwitch(isOn: $isOn, label: \"Label\"\(helperTextPatern)\(iconPatern)\(onErrorPatern)\(dividerPatern)\(orienationPatern)
\(disableCode))
"""
}
}

private var disableCode: String {
".disable(\(enabled ? "false" : "true"))"
}

private var helperTextPatern: String {
if helperText {
return ",helperText: \(String(localized: "app_components_switch_helperText_text"))"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

", helperText" avec un espace plutôt que ",helperText"

} else {
return ""
}
}
private var iconPatern: String {
if icon {
return ", Image(decorative: \"ic_heart\")"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le paramètre est nommé, il faudrait insérer "icon: "

} else {
return ""
}
}
private var onErrorPatern: String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"pattern" prend deux T, donc "onErrorPattern"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attention, il manque des sauts de ligne dans ce fichier, tout est collé.

if onError {
return ", onError: true"
} else {
return ""
}
}
private var dividerPatern: String {
if onError {
return ", divider: true"
} else {
return ""
}
}
private var orienationPatern: String {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"orientationPattern" plutôt que "orienationPatern".

if onError {
return ", orientation: \(orientation.description)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je ne suis pas convaincu par le notion d"orientation" qui me fait penser plutôt à portrait, paysage, portrait inversé.

Du côté du checkbox je prends la notion de "layout" pour gérer les trois cas : uniquement le selecteur, seelcteur à gauche et selecteur à droite.
Du coup, dans le construceur, je emttrais surtout un flag pour dire si on inverse le layout ou pas.

Tu peux regarder ici par exemple : https://github.com/Orange-OpenSource/ouds-ios/blob/264-add-component-checkbox-3/OUDS/Core/Components/Sources/Checkbox/OUDSCheckbox.swift

} else {
return ""
}
}
}

// MARK: - Switch Configuration View

struct SwitchConfiguration: View {

@Environment(\.theme) private var theme
@Environment(\.colorScheme) private var colorScheme

@StateObject var model: SwitchConfigurationModel

var body: some View {
VStack(alignment: .leading, spacing: theme.spaces.spaceFixedMedium) {
Toggle("app_common_enabled_label", isOn: $model.enabled)
.typeHeadingMedium(theme)
.foregroundStyle(theme.colors.colorContentDefault.color(for: colorScheme))

Toggle("app_components_switch_switchOnly_label", isOn: $model.switchOnly)
.typeHeadingMedium(theme)
.foregroundStyle(theme.colors.colorContentDefault.color(for: colorScheme))

if !model.switchOnly {
Toggle("app_components_common_helperText_label", isOn: $model.helperText)
.typeHeadingMedium(theme)
.foregroundStyle(theme.colors.colorContentDefault.color(for: colorScheme))

Toggle("app_components_common_icon_label", isOn: $model.icon)
.typeHeadingMedium(theme)
.foregroundStyle(theme.colors.colorContentDefault.color(for: colorScheme))

Toggle("app_components_common_divider_label", isOn: $model.divider)
.typeHeadingMedium(theme)
.foregroundStyle(theme.colors.colorContentDefault.color(for: colorScheme))

Toggle("app_components_common_onError_label", isOn: $model.onError)
.typeHeadingMedium(theme)
.foregroundStyle(theme.colors.colorContentDefault.color(for: colorScheme))

DesignToolboxChoicePicker(title: "app_components_common_orientation_label", selection: $model.orientation) {
ForEach(OUDSSwitch.Orientation.allCases, id: \.id) { orientation in
Text(LocalizedStringKey(orientation.description)).tag(orientation)
}
}

DisclosureGroup("app_components_common_editContent_label") {
DesignToolboxTextField(text: $model.labelContent, prompt: "app_components_common_userText_prompt", title: "app_components_switch_label_text")
if model.helperText {
DesignToolboxTextField(text: $model.helperTextContent, prompt: "app_components_common_userText_prompt", title: "app_components_common_helperText_label")
}
}
}
}
}
}

// MARK: Switch Layout Orientation extension

extension OUDSSwitch.Orientation: @retroactive CaseIterable, @retroactive CustomStringConvertible {
nonisolated(unsafe) public static let allCases: [OUDSSwitch.Orientation] = [.default, .inverse]

// Note: Not localized because it is a technical name
public var description: String {
switch self {
case .default:
"Default"
case .inverse:
"Inverse"
}
}

var id: String { description }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// 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 SwitchElement: DesignToolboxElement {
let name: String
let image: Image
let pageDescription: AnyView

init() {
name = "app_components_switch_label"
image = Image(decorative: "il_component_switch").renderingMode(.original)
pageDescription = AnyView(DesignToolboxElementPage(
name: name,
image: nil,
description: "app_components_switch_description_text",
illustration: AnyView(SwitchPage())
)
)
}
}
Loading
Loading