From 9dddad7efca0635664819e08a9ca3b7d609d7c14 Mon Sep 17 00:00:00 2001 From: Ludovic PINEL Date: Thu, 11 Jan 2024 09:40:35 +0100 Subject: [PATCH 1/5] Add limitation on title and on subtitle texts --- .../Components/Lists/ODSListItem.swift | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift index 64dcdd07..93ca5ec1 100644 --- a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift +++ b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift @@ -137,12 +137,18 @@ public struct ODSListItem: View { case checkmark(Bool) } + public enum SubtitleNumberOfLines: Int { + case one = 1 + case two = 2 + } + // ======================= // MARK: Stored Properties // ======================= private let title: Text private let subtitle: Text? + private let subtitleNumberOfLines: SubtitleNumberOfLines? private let leading: Leading? private let trailing: TrailingElement? private let height = ODSListItemModifier.defaultHeight @@ -156,14 +162,17 @@ public struct ODSListItem: View { /// - Parameters: /// - title: The primary text of the list item /// - subtitle: The secondary text of the list item (optional) + /// - subtitleNumberOfLines: If `subtitle` is provided, it is possible to limit the text + /// to 1 line or 2 lines. If set to nil, no restriction is applied (be carefull: this is not design compliant). /// - leading: The leading icon of the list item (optional) /// public init( title: Text, subtitle: Text? = nil, + subtitleNumberOfLines: SubtitleNumberOfLines? = .one, leading: Leading? = nil) { - self.init(title: title, subtitle: subtitle, leading: leading, trailing: nil) + self.init(title: title, subtitle: subtitle, subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailing: nil) } /// Describe the Item content with trailing text. @@ -171,16 +180,19 @@ public struct ODSListItem: View { /// - Parameters: /// - title: The primary text of the list item /// - subtitle: The secondary text of the list item (optional) + /// - subtitleNumberOfLines: If `subtitle` is provided, it is possible to limit the text + /// to 1 line or 2 lines. /// - leading: The leading icon of the list item (optional) /// - trailingText The text on trailing /// public init( title: Text, subtitle: Text? = nil, + subtitleNumberOfLines: SubtitleNumberOfLines? = .one, leading: Leading? = nil, trailingText: Text) { - self.init(title: title, subtitle: subtitle, leading: leading, trailing: .textOnly(trailingText)) + self.init(title: title, subtitle: subtitle, subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailing: .textOnly(trailingText)) } /// Describe the Item content with trailing text and iButton. @@ -188,6 +200,8 @@ public struct ODSListItem: View { /// - Parameters: /// - title: The primary text of the list item /// - subtitle: The secondary text of the list item (optional) + /// - subtitleNumberOfLines: If `subtitle` is provided, it is possible to limit the text + /// to 1 line or 2 lines. If set to nil, no restriction is applied (be carefull: this is not design compliant). /// - leading: The leading icon of the list item (optional) /// - trailingText The text on trailing /// - trailingIButtonAction: The action the i button on trailing @@ -195,11 +209,12 @@ public struct ODSListItem: View { public init( title: Text, subtitle: Text? = nil, + subtitleNumberOfLines: SubtitleNumberOfLines? = .one, leading: Leading? = nil, trailingText: Text? = nil, trailingIButtonAction: @escaping () -> Void) { - self.init(title: title, subtitle: subtitle, leading: leading, trailing: .iButton(trailingIButtonAction, trailingText)) + self.init(title: title, subtitle: subtitle, subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailing: .iButton(trailingIButtonAction, trailingText)) } /// Describe the Item content with trailing toggle. @@ -207,6 +222,8 @@ public struct ODSListItem: View { /// - Parameters: /// - title: The primary text of the list item /// - subtitle: The secondary text of the list item (optional) + /// - subtitleNumberOfLines: If `subtitle` is provided, it is possible to limit the text + /// to 1 line or 2 lines. If set to nil, no restriction is applied (be carefull: this is not design compliant). /// - leading: The leading icon of the list item (optional) /// - trailingText The text on trailing /// - trailingToggleIsOn: The binding to a property that determines whether the toggle is on or off. @@ -214,10 +231,11 @@ public struct ODSListItem: View { public init( title: Text, subtitle: Text? = nil, + subtitleNumberOfLines: SubtitleNumberOfLines? = .one, leading: Leading? = nil, trailingToggleIsOn: Binding) { - self.init(title: title, subtitle: subtitle, leading: leading, trailing: + self.init(title: title, subtitle: subtitle, subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailing: .toggle(trailingToggleIsOn)) } @@ -226,6 +244,8 @@ public struct ODSListItem: View { /// - Parameters: /// - title: The primary text of the list item /// - subtitle: The secondary text of the list item (optional) + /// - subtitleNumberOfLines: If `subtitle` is provided, it is possible to limit the text + /// to 1 line or 2 lines. If set to nil, no restriction is applied (be carefull: this is not design compliant). /// - leading: The leading icon of the list item (optional) /// - trailingText The text on trailing /// - trailingCheckmarkIsSelected: The flag to indicate if checkmark is visbile or not. @@ -233,10 +253,11 @@ public struct ODSListItem: View { public init( title: Text, subtitle: Text? = nil, + subtitleNumberOfLines: SubtitleNumberOfLines? = .one, leading: Leading? = nil, trailingCheckmarkIsSelected: Bool) { - self.init(title: title, subtitle: subtitle, leading: leading, trailing: .checkmark(trailingCheckmarkIsSelected)) + self.init(title: title, subtitle: subtitle, subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailing: .checkmark(trailingCheckmarkIsSelected)) } /// Describe the Item content with trailing element. @@ -244,17 +265,21 @@ public struct ODSListItem: View { /// - Parameters: /// - title: The primary text of the list item /// - subtitle: The secondary text of the list item (optional) + /// - subtitleNumberOfLines: If `subtitle` is provided, it is possible to limit the text + /// to 1 line or 2 lines. If set to nil, no restriction is applied (be carefull: this is not design compliant). /// - leading: The leading icon of the list item (optional) /// - trailing: The trailing element /// init( title: Text, subtitle: Text? = nil, + subtitleNumberOfLines: SubtitleNumberOfLines? = .one, leading: Leading? = nil, trailing: TrailingElement? = nil) { self.title = title self.subtitle = subtitle + self.subtitleNumberOfLines = subtitleNumberOfLines self.leading = leading self.trailing = trailing } @@ -272,12 +297,16 @@ public struct ODSListItem: View { VStack(alignment: .leading, spacing: ODSSpacing.none) { title + .lineLimit(1) + .truncationMode(.tail) .odsFont(.bodyLRegular) .foregroundColor(.primary) .frame(maxWidth: .infinity, alignment: .leading) .multilineTextAlignment(.leading) subtitle? + .lineLimit(subtitleNumberOfLines?.rawValue) + .truncationMode(.tail) .odsFont(.labelL) .foregroundColor(.primary) .multilineTextAlignment(.leading) From 1c438dece91512f58a2e7f617e1373700148ac16 Mon Sep 17 00:00:00 2001 From: Ludovic PINEL Date: Wed, 31 Jan 2024 10:08:50 +0100 Subject: [PATCH 2/5] Add configuration for subtitle --- .../project.pbxproj | 4 ++ .../Resources/Base.lproj/Localizable.strings | 4 ++ .../Resources/en.lproj/Localizable.strings | 5 +++ .../Resources/fr.lproj/Localizable.strings | 4 ++ .../ListItemSelectionVariant.swift | 18 ++++++-- .../ListItemSelectionVariantModel.swift | 4 +- .../ListItemSelectionVariantOptions.swift | 10 ++--- .../ListItemStandardVariant.swift | 19 ++++++-- .../ListItemStandardVariantModel.swift | 4 +- .../ListItemStandardVariantOptions.swift | 11 ++--- .../ListItemVariant/SubtitleOption.swift | 44 +++++++++++++++++++ 11 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SubtitleOption.swift diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj b/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj index c8084720..28d0bafc 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo.xcodeproj/project.pbxproj @@ -113,6 +113,7 @@ 07C3C7FE2AE7E56100833957 /* ListModuleOptionsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07C3C7FD2AE7E56100833957 /* ListModuleOptionsModel.swift */; }; 07E4C85C2AE7BC2D00FB4DAC /* ListModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E4C85B2AE7BC2D00FB4DAC /* ListModule.swift */; }; 07E4C8692AE7BC8E00FB4DAC /* ListModuleOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E4C8662AE7BC8E00FB4DAC /* ListModuleOptions.swift */; }; + 07F580152B69290300C8A00A /* SubtitleOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07F580142B69290300C8A00A /* SubtitleOption.swift */; }; 5107F55E2AE11BDD00D4D01F /* AppNews.json in Resources */ = {isa = PBXBuildFile; fileRef = 5107F5602AE11BDD00D4D01F /* AppNews.json */; }; 5107F5622AE1209A00D4D01F /* PrivacyNotice.html in Resources */ = {isa = PBXBuildFile; fileRef = 5107F5642AE1209A00D4D01F /* PrivacyNotice.html */; }; 5107F56A2AE1220900D4D01F /* CGU.html in Resources */ = {isa = PBXBuildFile; fileRef = 5107F56C2AE1220900D4D01F /* CGU.html */; }; @@ -267,6 +268,7 @@ 07C3C7FD2AE7E56100833957 /* ListModuleOptionsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListModuleOptionsModel.swift; sourceTree = ""; }; 07E4C85B2AE7BC2D00FB4DAC /* ListModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListModule.swift; sourceTree = ""; }; 07E4C8662AE7BC8E00FB4DAC /* ListModuleOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListModuleOptions.swift; sourceTree = ""; }; + 07F580142B69290300C8A00A /* SubtitleOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleOption.swift; sourceTree = ""; }; 2ACFE972C59B1460F410852D /* Pods-OrangeDesignSystemDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OrangeDesignSystemDemo.debug.xcconfig"; path = "Target Support Files/Pods-OrangeDesignSystemDemo/Pods-OrangeDesignSystemDemo.debug.xcconfig"; sourceTree = ""; }; 513876912ADD62A000AE53DF /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings; sourceTree = ""; }; 513C99F42B5812300043DAAE /* AppsPlus.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = AppsPlus.json; path = OrangeDesignSystemDemo/Resources/AppsPlus.json; sourceTree = ""; }; @@ -762,6 +764,7 @@ 07B94E072AD9891E00AAD1A5 /* SelectionVariant */, 07B94E062AD9890900AAD1A5 /* StandardVariant */, 077B673B2AE1500F0008C32B /* LeadingOption.swift */, + 07F580142B69290300C8A00A /* SubtitleOption.swift */, ); path = ListItemVariant; sourceTree = ""; @@ -1299,6 +1302,7 @@ 077C38512A9DDC79003D6B51 /* CapitalizedTextInputsVariant.swift in Sources */, 07B1A09C2B1E191F00ABF0A1 /* InputChipsVariant.swift in Sources */, 077C38632A9DDC79003D6B51 /* CardHorizontalVariant.swift in Sources */, + 07F580152B69290300C8A00A /* SubtitleOption.swift in Sources */, 077C38882A9DDC79003D6B51 /* CardViewDemo.swift in Sources */, 077C387F2A9DDC79003D6B51 /* TypographyGuideline.swift in Sources */, 077C389C2A9DEEDC003D6B51 /* RecipesLoader.swift in Sources */, diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings index c6711140..0da3f514 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings @@ -248,6 +248,10 @@ "screens.components.lists.alert" = "Information icon tapped! Bon appétit"; "screens.components.lists.options.description.info_button" = "Info button"; "screens.components.list.details" = "Details"; +"screens.components.lists.subtitle_option.title" = "Sous titre"; +"screens.components.lists.subtitle_option.none" = "Sans"; +"screens.components.lists.subtitle_option.one_line" = "Une ligne"; +"screens.components.lists.subtitle_option.two_lines" = "Deux ligne"; // ================================================== // MARK: - Screens - Components - Progress indicators diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/en.lproj/Localizable.strings b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/en.lproj/Localizable.strings index d5a38a0b..819627c1 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/en.lproj/Localizable.strings +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/en.lproj/Localizable.strings @@ -249,6 +249,11 @@ "screens.components.lists.alert" = "Information icon tapped! Bon appétit"; "screens.components.lists.options.description.info_button" = "Info button"; "screens.components.list.details" = "Details"; +"screens.components.lists.subtitle_option.title" = "Subtitle"; +"screens.components.lists.subtitle_option.none" = "None"; +"screens.components.lists.subtitle_option.one_line" = "One line"; +"screens.components.lists.subtitle_option.two_lines" = "Two lines"; + // ================================================== // MARK: - Screens - Components - Progress indicators diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings index d80ecad7..65cc55fe 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings @@ -248,6 +248,10 @@ "screens.components.lists.alert" = "Icône d'information tappée ! Bon appétit"; "screens.components.lists.options.description.info_button" = "Bouton d'information"; "screens.components.list.details" = "Détails"; +"screens.components.lists.subtitle_option.title" = "Subtitle"; +"screens.components.lists.subtitle_option.none" = "None"; +"screens.components.lists.subtitle_option.one_line" = "One line"; +"screens.components.lists.subtitle_option.two_lines" = "Two lines"; // ================================================== // MARK: - Screens - Components - Progress indicators diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift index cf82c6de..214fed06 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift @@ -74,6 +74,7 @@ private struct ListItemSelectionVariantInner: View { ODSListItem( title: title, subtitle: subtitle, + subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailingToggleIsOn: $isSelected) @@ -81,6 +82,7 @@ private struct ListItemSelectionVariantInner: View { ODSListItem( title: title, subtitle: subtitle, + subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailingCheckmarkIsSelected: isSelected) } @@ -91,13 +93,21 @@ private struct ListItemSelectionVariantInner: View { } private var subtitle: Text? { - if model.showSubtitle { - return Text(recipe.subtitle) - } else { - return nil + switch model.subtitleOption { + case .none: return nil + case .oneLine, .twoLines: return Text(recipe.description) } } + var subtitleNumberOfLines: ODSListItem.SubtitleNumberOfLines? { + switch model.subtitleOption { + case .none: return nil + case .oneLine: return .one + case .twoLines: return .two + } + } + + private var leading: ODSListItem.Leading? { let emptyImage = Image("ods_empty", bundle: Bundle.ods) switch model.leadingOption { diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift index 2181f392..b68ecc02 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift @@ -42,7 +42,7 @@ final class ListItemSelectionVariantModel: ObservableObject { // MARK: Stored properties // ======================= - @Published var showSubtitle: Bool + @Published var subtitleOption: SubtitleOption @Published var leadingOption: LeadingOption @Published var trailingOption: SelectionTrailingOption @@ -50,7 +50,7 @@ final class ListItemSelectionVariantModel: ObservableObject { // MARK: Initializers // ================== init() { - showSubtitle = true + subtitleOption = .twoLines leadingOption = .circle trailingOption = .toggle } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantOptions.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantOptions.swift index fb6f5ffb..8bd590d2 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantOptions.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantOptions.swift @@ -28,11 +28,11 @@ struct ListItemSelectionVariantOptions: View { var body: some View { VStack(spacing: ODSSpacing.none) { - Toggle(isOn: $model.showSubtitle) { - Text("shared.subtitle").odsFont(.bodyLBold) - } - .padding(.horizontal, ODSSpacing.m) - .padding(.vertical, ODSSpacing.s) + ODSChoiceChipPicker( + title: Text("screens.components.lists.subtitle_option.title"), + chips: SubtitleOption.chips, + selection: $model.subtitleOption) + .padding(.vertical, ODSSpacing.s) ODSChoiceChipPicker( title: Text("shared.leading"), diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift index b2ffe7fe..a2fe5e1a 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift @@ -84,6 +84,7 @@ private struct ListItemStandardVariantInner: View { ODSListItem( title: title, subtitle: subtitle, + subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailingText: Text("screens.components.list.details")) { @@ -93,6 +94,7 @@ private struct ListItemStandardVariantInner: View { ODSListItem( title: title, subtitle: subtitle, + subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailingText: Text("screens.components.list.details")) @@ -100,6 +102,7 @@ private struct ListItemStandardVariantInner: View { ODSListItem( title: title, subtitle: subtitle, + subtitleNumberOfLines: subtitleNumberOfLines, leading: leading) { iButtonAction() @@ -109,6 +112,7 @@ private struct ListItemStandardVariantInner: View { ODSListItem( title: title, subtitle: subtitle, + subtitleNumberOfLines: subtitleNumberOfLines, leading: leading) } } @@ -118,10 +122,17 @@ private struct ListItemStandardVariantInner: View { } private var subtitle: Text? { - if model.showSubtitle { - return Text(recipe.subtitle) - } else { - return nil + switch model.subtitleOption { + case .none: return nil + case .oneLine, .twoLines: return Text(recipe.subtitle) + } + } + + var subtitleNumberOfLines: ODSListItem.SubtitleNumberOfLines? { + switch model.subtitleOption { + case .none: return nil + case .oneLine: return .one + case .twoLines: return .two } } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift index d4dff576..9fb98ebf 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift @@ -46,7 +46,7 @@ class ListItemStandardVariantModel: ObservableObject { // MARK: Stored properties // ======================= - @Published var showSubtitle: Bool + @Published var subtitleOption: SubtitleOption @Published var leadingOption: LeadingOption @Published var trailingOptions: [StandardTrailingOption] @Published var navigate: Bool @@ -55,7 +55,7 @@ class ListItemStandardVariantModel: ObservableObject { // MARK: Initializers // ================== init() { - showSubtitle = true + subtitleOption = .twoLines leadingOption = .circle trailingOptions = [] navigate = true diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantOptions.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantOptions.swift index f0f7ac9d..5f1273b7 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantOptions.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantOptions.swift @@ -28,11 +28,12 @@ struct ListItemStandardVariantOptions: View { var body: some View { VStack(spacing: ODSSpacing.none) { - Toggle(isOn: $model.showSubtitle) { - Text("shared.subtitle").odsFont(.bodyLBold) - } - .padding(.horizontal, ODSSpacing.m) - .padding(.vertical, ODSSpacing.s) + + ODSChoiceChipPicker( + title: Text("screens.components.lists.subtitle_option.title"), + chips: SubtitleOption.chips, + selection: $model.subtitleOption) + .padding(.vertical, ODSSpacing.s) ODSChoiceChipPicker( title: Text("shared.leading"), diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SubtitleOption.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SubtitleOption.swift new file mode 100644 index 00000000..ca8bdc2d --- /dev/null +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SubtitleOption.swift @@ -0,0 +1,44 @@ +// +// Software Name: Orange Design System +// SPDX-FileCopyrightText: Copyright (c) Orange SA +// SPDX-License-Identifier: MIT +// +// This software is distributed under the MIT licence, +// 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 Design System +// + +import OrangeDesignSystem +import SwiftUI + +// ============= +// MARK: Options +// ============= + +enum SubtitleOption: Int, CaseIterable { + case none + case oneLine + case twoLines + + var description: LocalizedStringKey { + switch self { + case .none: + return "screens.components.lists.subtitle_option.none" + case .oneLine: + return "screens.components.lists.subtitle_option.one_line" + case .twoLines: + return "screens.components.lists.subtitle_option.two_lines" + } + } + + var chip: ODSChoiceChip { + .init(text: Text(description), value: self) + } + + static var chips: [ODSChoiceChip] { + Self.allCases.map { $0.chip } + } +} From 4e8b91eabec02d9b58d081e1e126abca766ecd55 Mon Sep 17 00:00:00 2001 From: Ludovic PINEL Date: Wed, 31 Jan 2024 10:12:46 +0100 Subject: [PATCH 3/5] Uopdate change logfile --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 931c08e1..8381490a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased](https://github.com/Orange-OpenSource/ods-ios/compare/0.16.0...qualif) +- [DemoAPP] Add configuration in the ListItem screeen to select the number of lines in subtitle([#650](https://github.com/Orange-OpenSource/ods-ios/issues/650)) +- [SDK] Update ListItem to limit title in one line and subtitle up to two lines ([#586](https://github.com/Orange-OpenSource/ods-ios/issues/586)) - [DemoApp/SDK] Components page accessibility issues (Bug [#563](https://github.com/Orange-OpenSource/ods-ios/issues/563)) - [DemoApp/SDK] Code cleanup ([#647](https://github.com/Orange-OpenSource/ods-ios/issues/647)]) - [SDK] Update Banners to align buttons when text is too long ([#642](https://github.com/Orange-OpenSource/ods-ios/issues/642)) From f00893b1ebd5904d19e583cf6e0aacd9b7cc2468 Mon Sep 17 00:00:00 2001 From: Ludovic PINEL Date: Wed, 31 Jan 2024 11:38:51 +0100 Subject: [PATCH 4/5] Add pullToRefresh to update screen with a new recipe --- .../Lists/Internal/TrailingView.swift | 8 +++---- .../Components/Lists/ODSListItem.swift | 12 ++++++++++ .../ListItemSelectionVariant.swift | 24 +++++++++++++------ .../ListItemSelectionVariantModel.swift | 7 ++++++ .../ListItemStandardVariant.swift | 24 +++++++++++++------ .../ListItemStandardVariantModel.swift | 7 ++++++ .../Utils/Domain/Recipes/RecipesBook.swift | 5 ++++ 7 files changed, 69 insertions(+), 18 deletions(-) diff --git a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift index ef5854d0..852c8766 100644 --- a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift +++ b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift @@ -45,10 +45,10 @@ struct TrailingView: View { .buttonStyle(PlainButtonStyle()) } - case let .toggle(isOn): - Toggle(isOn: isOn) { - EmptyView() - } + case .toggle: + // Do nothing here, because toggle is always + // manage in ODSListItem. + EmptyView() case let .checkmark(isVisible): if isVisible { diff --git a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift index 93ca5ec1..dc52309f 100644 --- a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift +++ b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/ODSListItem.swift @@ -289,6 +289,18 @@ public struct ODSListItem: View { // ========== public var body: some View { + if case .toggle(let isOn) = trailing { + // Must be manage here, because if it is manged in + // TrailingView, an extra content (blank) is added by the SwiftUI.Toggle. + Toggle(isOn: isOn) { + content + } + } else { + content + } + } + + private var content: some View { HStack(alignment: .center, spacing: ODSSpacing.s) { if let leading = self.leading { LeadingView(element: leading, height: height) diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift index 214fed06..8b230417 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariant.swift @@ -43,8 +43,15 @@ private struct ListItemSelectionVariantInner: View { @ObservedObject var model: ListItemSelectionVariantModel @State private var isSelected: Bool = true - private let recipe: Recipe = RecipeBook.shared.recipes[0] + + // ================= + // MARK: Initializer + // ================= + init(model: ListItemSelectionVariantModel) { + self.model = model + } + // ========== // MARK: Body // ========== @@ -59,6 +66,9 @@ private struct ListItemSelectionVariantInner: View { } } } + .refreshable { + model.updateRecipe() + } .listStyle(.plain) .navigationBarTitleDisplayMode(.inline) } @@ -89,13 +99,13 @@ private struct ListItemSelectionVariantInner: View { } private var title: Text { - Text(recipe.title) + Text(model.recipe.title) } private var subtitle: Text? { switch model.subtitleOption { case .none: return nil - case .oneLine, .twoLines: return Text(recipe.description) + case .oneLine, .twoLines: return Text(model.recipe.description) } } @@ -114,13 +124,13 @@ private struct ListItemSelectionVariantInner: View { case .none: return nil case .icon: - return .icon(Image(recipe.iconName)) + return .icon(Image(model.recipe.iconName)) case .circle: - return .circularImage(source: .asyncImage(recipe.url, emptyImage)) + return .circularImage(source: .asyncImage(model.recipe.url, emptyImage)) case .square: - return .squareImage(source: .asyncImage(recipe.url, emptyImage)) + return .squareImage(source: .asyncImage(model.recipe.url, emptyImage)) case .wide: - return .wideImage(source: .asyncImage(recipe.url, emptyImage)) + return .wideImage(source: .asyncImage(model.recipe.url, emptyImage)) } } } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift index b68ecc02..1f3948e1 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/SelectionVariant/ListItemSelectionVariantModel.swift @@ -45,6 +45,7 @@ final class ListItemSelectionVariantModel: ObservableObject { @Published var subtitleOption: SubtitleOption @Published var leadingOption: LeadingOption @Published var trailingOption: SelectionTrailingOption + @Published var recipe: Recipe // ================== // MARK: Initializers @@ -53,5 +54,11 @@ final class ListItemSelectionVariantModel: ObservableObject { subtitleOption = .twoLines leadingOption = .circle trailingOption = .toggle + self.recipe = RecipeBook.shared.randomRecipe() + } + + func updateRecipe() { + recipe = RecipeBook.shared.randomRecipe() } } + diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift index a2fe5e1a..d8ed24cd 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariant.swift @@ -43,8 +43,15 @@ private struct ListItemStandardVariantInner: View { @ObservedObject var model: ListItemStandardVariantModel @State private var showAlert: Bool = false - private let recipe: Recipe = RecipeBook.shared.recipes[0] + + // ================= + // MARK: Initializer + // ================= + init(model: ListItemStandardVariantModel) { + self.model = model + } + // ========== // MARK: Body // ========== @@ -63,6 +70,9 @@ private struct ListItemStandardVariantInner: View { .odsListItemStyle() } } + .refreshable { + model.updateRecipe() + } .listStyle(.plain) .navigationBarTitleDisplayMode(.inline) .alert("screens.components.lists.alert", isPresented: $showAlert) { @@ -118,13 +128,13 @@ private struct ListItemStandardVariantInner: View { } private var title: Text { - Text(recipe.title) + Text(model.recipe.title) } private var subtitle: Text? { switch model.subtitleOption { case .none: return nil - case .oneLine, .twoLines: return Text(recipe.subtitle) + case .oneLine, .twoLines: return Text(model.recipe.subtitle) } } @@ -142,13 +152,13 @@ private struct ListItemStandardVariantInner: View { case .none: return nil case .icon: - return .icon(Image(recipe.iconName)) + return .icon(Image(model.recipe.iconName)) case .circle: - return .circularImage(source: .asyncImage(recipe.url, emptyImage)) + return .circularImage(source: .asyncImage(model.recipe.url, emptyImage)) case .square: - return .squareImage(source: .asyncImage(recipe.url, emptyImage)) + return .squareImage(source: .asyncImage(model.recipe.url, emptyImage)) case .wide: - return .wideImage(source: .asyncImage(recipe.url, emptyImage)) + return .wideImage(source: .asyncImage(model.recipe.url, emptyImage)) } } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift index 9fb98ebf..8c5e639d 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Screens/Components/Pages/Lists/ListItemVariant/StandardVariant/ListItemStandardVariantModel.swift @@ -50,6 +50,7 @@ class ListItemStandardVariantModel: ObservableObject { @Published var leadingOption: LeadingOption @Published var trailingOptions: [StandardTrailingOption] @Published var navigate: Bool + @Published var recipe: Recipe // ================== // MARK: Initializers @@ -59,5 +60,11 @@ class ListItemStandardVariantModel: ObservableObject { leadingOption = .circle trailingOptions = [] navigate = true + + self.recipe = RecipeBook.shared.randomRecipe() + } + + func updateRecipe() { + recipe = RecipeBook.shared.randomRecipe() } } diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/Domain/Recipes/RecipesBook.swift b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/Domain/Recipes/RecipesBook.swift index cca4d1cf..1217fa48 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/Domain/Recipes/RecipesBook.swift +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Utils/Domain/Recipes/RecipesBook.swift @@ -21,6 +21,11 @@ struct RecipeBook { let foods: [Food] static let shared: RecipeBook = .init() + + func randomRecipe() -> Recipe { + let selectedRecipesIndex = Int.random(in: 0.. Date: Wed, 31 Jan 2024 15:16:51 +0100 Subject: [PATCH 5/5] review: fix mistakes --- CHANGELOG.md | 4 ++-- .../Components/Lists/Internal/TrailingView.swift | 3 +-- .../Resources/Base.lproj/Localizable.strings | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8381490a..f46bf6e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,14 +5,14 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased](https://github.com/Orange-OpenSource/ods-ios/compare/0.16.0...qualif) -- [DemoAPP] Add configuration in the ListItem screeen to select the number of lines in subtitle([#650](https://github.com/Orange-OpenSource/ods-ios/issues/650)) +- [DemoApp] Add configuration in the ListItem screeen to select the number of lines in subtitle([#650](https://github.com/Orange-OpenSource/ods-ios/issues/650)) - [SDK] Update ListItem to limit title in one line and subtitle up to two lines ([#586](https://github.com/Orange-OpenSource/ods-ios/issues/586)) - [DemoApp/SDK] Components page accessibility issues (Bug [#563](https://github.com/Orange-OpenSource/ods-ios/issues/563)) - [DemoApp/SDK] Code cleanup ([#647](https://github.com/Orange-OpenSource/ods-ios/issues/647)]) - [SDK] Update Banners to align buttons when text is too long ([#642](https://github.com/Orange-OpenSource/ods-ios/issues/642)) - [SDK] Update Cards to align buttons when text is too long ([#630](https://github.com/Orange-OpenSource/ods-ios/issues/630)) - [Tooling] Upgrate to xcode 15 ([#638](https://github.com/Orange-OpenSource/ods-ios/issues/638)) -- [DemoApp/SDK] ODSSmallCard and GridOfSmallCards a11i issue if accessible text sizes in use ([#598](https://github.com/Orange-OpenSource/ods-ios/issues/598)) +- [DemoApp/SDK] ODSSmallCard and GridOfSmallCards a11y issue if accessible text sizes in use ([#598](https://github.com/Orange-OpenSource/ods-ios/issues/598)) - [Tooling] Upgrade to Xcode 15 ([#638](https://github.com/Orange-OpenSource/ods-ios/issues/638)) - [Tooling] Upgrade tools versions and internal librairies ([#639](https://github.com/Orange-OpenSource/ods-ios/issues/639)) - [Docs] Update documentation with illustration ([#602](https://github.com/Orange-OpenSource/ods-ios/issues/602)) diff --git a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift index 852c8766..92b55c0a 100644 --- a/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift +++ b/OrangeDesignSystem/Sources/OrangeDesignSystem/Components/Lists/Internal/TrailingView.swift @@ -46,8 +46,7 @@ struct TrailingView: View { } case .toggle: - // Do nothing here, because toggle is always - // manage in ODSListItem. + // Do nothing here, because toggle is always managed in ODSListItem. EmptyView() case let .checkmark(isVisible): diff --git a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings index 0da3f514..77c3015c 100644 --- a/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings +++ b/OrangeDesignSystemDemo/OrangeDesignSystemDemo/Resources/Base.lproj/Localizable.strings @@ -251,7 +251,7 @@ "screens.components.lists.subtitle_option.title" = "Sous titre"; "screens.components.lists.subtitle_option.none" = "Sans"; "screens.components.lists.subtitle_option.one_line" = "Une ligne"; -"screens.components.lists.subtitle_option.two_lines" = "Deux ligne"; +"screens.components.lists.subtitle_option.two_lines" = "Deux lignes"; // ================================================== // MARK: - Screens - Components - Progress indicators