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

[#586] Update ListItem to limit title to one line and subtitle up to two lines #656

Merged
merged 5 commits into from
Jan 31, 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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +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))
- [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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ struct TrailingView: View {
.buttonStyle(PlainButtonStyle())
}

case let .toggle(isOn):
Toggle(isOn: isOn) {
EmptyView()
}
case .toggle:
ludovic35 marked this conversation as resolved.
Show resolved Hide resolved
// Do nothing here, because toggle is always managed in ODSListItem.
EmptyView()

case let .checkmark(isVisible):
if isVisible {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -156,68 +162,80 @@ 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.
///
/// - 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.
///
/// - 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
///
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.
///
/// - 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.
///
public init(
title: Text,
subtitle: Text? = nil,
subtitleNumberOfLines: SubtitleNumberOfLines? = .one,
leading: Leading? = nil,
trailingToggleIsOn: Binding<Bool>)
{
self.init(title: title, subtitle: subtitle, leading: leading, trailing:
self.init(title: title, subtitle: subtitle, subtitleNumberOfLines: subtitleNumberOfLines, leading: leading, trailing:
.toggle(trailingToggleIsOn))
}

Expand All @@ -226,35 +244,42 @@ 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.
///
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.
///
/// - 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
}
Expand All @@ -264,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)
Expand All @@ -272,12 +309,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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -267,6 +268,7 @@
07C3C7FD2AE7E56100833957 /* ListModuleOptionsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListModuleOptionsModel.swift; sourceTree = "<group>"; };
07E4C85B2AE7BC2D00FB4DAC /* ListModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListModule.swift; sourceTree = "<group>"; };
07E4C8662AE7BC8E00FB4DAC /* ListModuleOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListModuleOptions.swift; sourceTree = "<group>"; };
07F580142B69290300C8A00A /* SubtitleOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleOption.swift; sourceTree = "<group>"; };
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 = "<group>"; };
513876912ADD62A000AE53DF /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = OrangeDesignSystemDemo/Resources/fr.lproj/Localizable.strings; sourceTree = "<group>"; };
513C99F42B5812300043DAAE /* AppsPlus.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = AppsPlus.json; path = OrangeDesignSystemDemo/Resources/AppsPlus.json; sourceTree = "<group>"; };
Expand Down Expand Up @@ -762,6 +764,7 @@
07B94E072AD9891E00AAD1A5 /* SelectionVariant */,
07B94E062AD9890900AAD1A5 /* StandardVariant */,
077B673B2AE1500F0008C32B /* LeadingOption.swift */,
07F580142B69290300C8A00A /* SubtitleOption.swift */,
);
path = ListItemVariant;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 lignes";

// ==================================================
// MARK: - Screens - Components - Progress indicators
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ==========
Expand All @@ -59,6 +66,9 @@ private struct ListItemSelectionVariantInner: View {
}
}
}
.refreshable {
model.updateRecipe()
}
.listStyle(.plain)
.navigationBarTitleDisplayMode(.inline)
}
Expand All @@ -74,43 +84,53 @@ private struct ListItemSelectionVariantInner: View {
ODSListItem(
title: title,
subtitle: subtitle,
subtitleNumberOfLines: subtitleNumberOfLines,
leading: leading,
trailingToggleIsOn: $isSelected)

case .checkmark:
ODSListItem(
title: title,
subtitle: subtitle,
subtitleNumberOfLines: subtitleNumberOfLines,
leading: leading,
trailingCheckmarkIsSelected: isSelected)
}
}

private var title: Text {
Text(recipe.title)
Text(model.recipe.title)
}

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(model.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 {
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))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,23 @@ final class ListItemSelectionVariantModel: ObservableObject {
// MARK: Stored properties
// =======================

@Published var showSubtitle: Bool
@Published var subtitleOption: SubtitleOption
@Published var leadingOption: LeadingOption
@Published var trailingOption: SelectionTrailingOption
@Published var recipe: Recipe

// ==================
// MARK: Initializers
// ==================
init() {
showSubtitle = true
subtitleOption = .twoLines
leadingOption = .circle
trailingOption = .toggle
self.recipe = RecipeBook.shared.randomRecipe()
}

func updateRecipe() {
recipe = RecipeBook.shared.randomRecipe()
}
}

Loading
Loading