diff --git a/Backpack-SwiftUI/ChipGroup/Classes/BPKMultiSelectChipGroup.swift b/Backpack-SwiftUI/ChipGroup/Classes/BPKMultiSelectChipGroup.swift new file mode 100644 index 000000000..2263225e4 --- /dev/null +++ b/Backpack-SwiftUI/ChipGroup/Classes/BPKMultiSelectChipGroup.swift @@ -0,0 +1,208 @@ +/* + * Backpack - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SwiftUI + +/// A Group of chips that allows multiple chips to be selected at a time. +public struct BPKMultiSelectChipGroup: View { + private let chips: [ChipItem] + private let style: BPKChipStyle + private let type: ChipGroupType + + public init( + chips: [ChipItem], + style: BPKChipStyle = .default, + type: ChipGroupType = .rail(stickyChip: nil) + ) { + self.chips = chips + self.style = style + self.type = type + } + + public var body: some View { + switch type { + case let .rail(stickyChip): + HStack(spacing: BPKSpacing.none) { + if let stickyChip { + BPKStickyChip(stickyChip: stickyChip, style: style) + Color(BPKColor.lineColor) + .frame(width: 1) + .frame(height: .xl) + .padding(.leading, .md) + } + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: .md) { + chipsListView + } + .if(stickyChip != nil, transform: { + $0.padding(.leading, .md) + }) + .padding(.vertical, .sm) + } + } + case .wrap: + FlowStackView(spacing: .init(width: .md, height: .md)) { + chipsListView + } + } + } + + private var chipsListView: some View { + ForEach(0.. some View { + switch chip.type { + case .option, .dropdown: + BPKChip( + chip.text, + icon: chip.icon, + selected: chip.selected, + style: style, + onClick: chip.onClick + ) + case .dismiss: + BPKDismissableChip( + chip.text, + icon: chip.icon, + style: style, + onClick: chip.onClick + ) + } + } +} + +public extension BPKMultiSelectChipGroup.ChipItem { + enum ChipType { + case option, dropdown, dismiss + } +} + +public extension BPKMultiSelectChipGroup { + enum ChipGroupType { + case rail(stickyChip: StickyChipItem?) + case wrap + } + + struct StickyChipItem { + let accessibilityLabel: String + let icon: BPKIcon + let selected: Bool + let onClick: () -> Void + + public init( + accessibilityLabel: String, + icon: BPKIcon, + selected: Bool, + onClick: @escaping () -> Void + ) { + self.accessibilityLabel = accessibilityLabel + self.icon = icon + self.selected = selected + self.onClick = onClick + } + } + + struct ChipItem { + let text: String + let icon: BPKIcon? + var type: ChipType + var selected: Bool + let onClick: () -> Void + + public init( + text: String, + icon: BPKIcon? = nil, + type: ChipType = .option, + selected: Bool, + onClick: @escaping () -> Void + ) { + self.text = text + self.icon = icon + self.type = type + self.selected = selected + self.onClick = onClick + } + } +} + +struct BPKMultiSelectChipGroup_Previews: PreviewProvider { + + static var previews: some View { + let chips: [BPKMultiSelectChipGroup.ChipItem] = [ + .init(text: "Shenzhen", selected: false, onClick: {}), + .init(text: "London", selected: false, onClick: {}), + .init(text: "Edinburgh", selected: true, onClick: {}), + .init(text: "Manchester", selected: false, onClick: {}), + .init(text: "Belfast", selected: true, onClick: {}), + .init(text: "Glasgow", selected: false, onClick: {}), + .init(text: "Gurham", selected: false, onClick: {}) + ] + VStack { + BPKText("Rail", style: .heading3) + BPKMultiSelectChipGroup( + chips: chips, + type: .rail(stickyChip: BPKMultiSelectChipGroup.StickyChipItem( + accessibilityLabel: "Filters", + icon: .filter, + selected: false, + onClick: {} + )) + ) + .padding() + BPKMultiSelectChipGroup( + chips: chips, + style: .onDark + ) + .padding() + .background(.surfaceContrastColor) + BPKMultiSelectChipGroup( + chips: chips, + style: .onImage + ) + .padding() + .background(.statusSuccessSpotColor) + } + VStack { + BPKText("Wrap", style: .heading3) + BPKMultiSelectChipGroup( + chips: chips, + type: .wrap + ) + .padding() + BPKMultiSelectChipGroup( + chips: chips, + style: .onDark, + type: .wrap + ) + .padding() + .background(.surfaceContrastColor) + + BPKMultiSelectChipGroup( + chips: chips, + style: .onImage, + type: .wrap + ) + .padding() + .background(.statusSuccessSpotColor) + } + } +} diff --git a/Backpack-SwiftUI/ChipGroup/Classes/BPKStickyChip.swift b/Backpack-SwiftUI/ChipGroup/Classes/BPKStickyChip.swift new file mode 100644 index 000000000..83f9686c5 --- /dev/null +++ b/Backpack-SwiftUI/ChipGroup/Classes/BPKStickyChip.swift @@ -0,0 +1,41 @@ +/* + * Backpack - Skyscanner's Design System + * + * Copyright 2018 Skyscanner Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SwiftUI + +struct BPKStickyChip: View { + let stickyChip: BPKMultiSelectChipGroup.StickyChipItem + let style: BPKChipStyle + + var body: some View { + Button(action: stickyChip.onClick) { + BPKIconView(stickyChip.icon) + .padding(.horizontal, .md) + } + .buttonStyle( + ChipButtonStyle( + style: style, + selected: stickyChip.selected, + disabled: false + ) + ) + .accessibilityAddTraits(stickyChip.selected ? [.isSelected] : []) + .sizeCategory(.large) + .accessibilityLabel(stickyChip.accessibilityLabel) + } +} diff --git a/Backpack-SwiftUI/ChipGroup/README.md b/Backpack-SwiftUI/ChipGroup/README.md index 845c912ba..2156f8642 100644 --- a/Backpack-SwiftUI/ChipGroup/README.md +++ b/Backpack-SwiftUI/ChipGroup/README.md @@ -19,7 +19,10 @@ ## Usage -Create ChipItems that used in the BPKSingleSelectChipGroup +### Single Select + +Create ChipItems to be used in the group. + ```swift let chips: [BPKSingleSelectChipGroup.ChipItem] = [ .init(text: "Shenzhen", icon: .city), @@ -32,55 +35,110 @@ let chips: [BPKSingleSelectChipGroup.ChipItem] = [ ] ``` -Single line group without default selected item: -```swift -BPKSingleSelectChipGroup( - chips: chips, - selectedIndex: .constant(nil) -) { - print("Chip item tapped") -} -``` +#### Single line group -Single line group with specific selected item: ```swift +@State var selectedIndex: Int? = nil BPKSingleSelectChipGroup( chips: chips, - selectedIndex: .constant(2) + selectedIndex: selectedIndex, + type: .rail ) { print("Chip item tapped") } ``` -Single line group on dark background: +#### Single line group on dark background: + ```swift BPKSingleSelectChipGroup( chips: chips, style: .onDark, - selectedIndex: .constant(2) + selectedIndex: selectedIndex ) { print("Chip item tapped") } ``` -Single line group on an image background: +#### Single line group on an image background: + ```swift BPKSingleSelectChipGroup( chips: chips, style: .onImage, - selectedIndex: .constant(2) + selectedIndex: selectedIndex ) { print("Chip item tapped") } ``` -Multiple lines of chips group +#### Multiple lines of chips group + ```swift BPKSingleSelectChipGroup( chips: chips, - selectedIndex: .constant(2), + selectedIndex: selectedIndex, type: .wrap ) { print("Chip item tapped") } ``` + +### Multiple Select + +Create ChipItems to be used in the group. + +```swift +@State var chips: [BPKMultiSelectChipGroup.ChipItem] = [ + .init(text: "Shenzhen", icon: .city, selected: true), + .init(text: "London", icon: .city, selected: true), + .init(text: "Edinburgh", selected: false), + .init(text: "Manchester", selected: false), + .init(text: "Belfast", selected: false), +] +``` + +#### Single line group + +```swift +BPKMultiSelectChipGroup( + chips: chips, + type: .rail(stickyChip: nil) +) +``` + +#### Single line group on dark background: + +```swift +BPKMultiSelectChipGroup( + chips: chips, + style: .onDark +) +``` + +#### Single line group on an image background: + +```swift +BPKMultiSelectChipGroup( + chips: chips, + style: .onImage +) +``` + +#### Single line group with a sticky chip: + +```swift +BPKMultiSelectChipGroup( + chips: chips, + type: .rail(stickyChip: .init(accessibilityLabel: "Filters", icon: .filter, selected: false)) +) +``` + +#### Multiple lines of chips group + +```swift +BPKMultiSelectChipGroup( + chips: chips, + type: .wrap +) +``` \ No newline at end of file diff --git a/Backpack-SwiftUI/Tests/ChipGroup/BPKChipGroupTests.swift b/Backpack-SwiftUI/Tests/ChipGroup/BPKChipGroupTests.swift index 6aea17287..b03211d4a 100644 --- a/Backpack-SwiftUI/Tests/ChipGroup/BPKChipGroupTests.swift +++ b/Backpack-SwiftUI/Tests/ChipGroup/BPKChipGroupTests.swift @@ -22,16 +22,18 @@ import SwiftUI // swiftlint:disable closure_body_length class BPKChipGroupTests: XCTestCase { + let singleChips: [BPKSingleSelectChipGroup.ChipItem] = [ + .init(text: "Barcelona"), + .init(text: "Tokio", icon: .city), + .init(text: "London"), + .init(text: "Shenzhen") + ] + func test_singleSelect_railChips_default() { assertSnapshot( VStack { BPKSingleSelectChipGroup( - chips: [ - .init(text: "Barcelona"), - .init(text: "Tokio", icon: .city), - .init(text: "London"), - .init(text: "Shenzhen") - ], + chips: singleChips, style: .default, selectedIndex: .constant(1), type: .rail, @@ -40,12 +42,7 @@ class BPKChipGroupTests: XCTestCase { .padding() BPKSingleSelectChipGroup( - chips: [ - .init(text: "Barcelona"), - .init(text: "Tokio", icon: .city), - .init(text: "London"), - .init(text: "Shenzhen") - ], + chips: singleChips, style: .onDark, selectedIndex: .constant(1), type: .rail, @@ -55,12 +52,7 @@ class BPKChipGroupTests: XCTestCase { .background(.surfaceContrastColor) BPKSingleSelectChipGroup( - chips: [ - .init(text: "Barcelona"), - .init(text: "Tokio", icon: .city), - .init(text: "London"), - .init(text: "Shenzhen") - ], + chips: singleChips, style: .onImage, selectedIndex: .constant(1), type: .rail, @@ -77,12 +69,7 @@ class BPKChipGroupTests: XCTestCase { assertSnapshot( VStack { BPKSingleSelectChipGroup( - chips: [ - .init(text: "Barcelona"), - .init(text: "Tokio", icon: .city), - .init(text: "London"), - .init(text: "Shenzhen") - ], + chips: singleChips, style: .default, selectedIndex: .constant(1), type: .wrap, @@ -91,12 +78,7 @@ class BPKChipGroupTests: XCTestCase { .padding() BPKSingleSelectChipGroup( - chips: [ - .init(text: "Barcelona"), - .init(text: "Tokio", icon: .city), - .init(text: "London"), - .init(text: "Shenzhen") - ], + chips: singleChips, style: .onDark, selectedIndex: .constant(1), type: .wrap, @@ -106,12 +88,7 @@ class BPKChipGroupTests: XCTestCase { .background(.surfaceContrastColor) BPKSingleSelectChipGroup( - chips: [ - .init(text: "Barcelona"), - .init(text: "Tokio", icon: .city), - .init(text: "London"), - .init(text: "Shenzhen") - ], + chips: singleChips, style: .onImage, selectedIndex: .constant(1), type: .wrap, @@ -124,4 +101,108 @@ class BPKChipGroupTests: XCTestCase { .frame(width: 350) ) } + + let multiselectChips: [BPKMultiSelectChipGroup.ChipItem] = [ + .init(text: "Barcelona", selected: false, onClick: {}), + .init(text: "Tokio", icon: .city, selected: true, onClick: {}), + .init(text: "London", selected: true, onClick: {}), + .init(text: "Shenzhen", selected: false, onClick: {}) + ] + + func test_multipleSelect_railChips_default() { + assertSnapshot( + VStack { + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .default, + type: .rail(stickyChip: nil) + ) + .padding() + + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .onDark, + type: .rail(stickyChip: nil) + ) + .padding() + .background(.surfaceContrastColor) + + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .onImage, + type: .rail(stickyChip: nil) + ) + .padding() + .background(.statusSuccessSpotColor) + } + .frame(width: 300) + ) + } + + func test_multipleSelect_railWithStickyChips_default() { + let sticky = BPKMultiSelectChipGroup.StickyChipItem( + accessibilityLabel: "", + icon: .filter, + selected: false, + onClick: {} + ) + assertSnapshot( + VStack { + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .default, + type: .rail(stickyChip: sticky) + ) + .padding() + + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .onDark, + type: .rail(stickyChip: sticky) + ) + .padding() + .background(.surfaceContrastColor) + + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .onImage, + type: .rail(stickyChip: sticky) + ) + .padding() + .background(.statusSuccessSpotColor) + } + .frame(width: 300) + ) + } + + func test_multipleSelect_wrapChips_onDark() { + assertSnapshot( + VStack { + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .default, + type: .wrap + ) + .padding() + + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .onDark, + type: .wrap + ) + .padding() + .background(.surfaceContrastColor) + + BPKMultiSelectChipGroup( + chips: multiselectChips, + style: .onImage, + type: .wrap + ) + .padding() + .background(.statusSuccessSpotColor) + + } + .frame(width: 350) + ) + } } diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.dark-mode.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.dark-mode.png new file mode 100644 index 000000000..aa9cfedcf Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.dark-mode.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.light-mode.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.light-mode.png new file mode 100644 index 000000000..c2602db2b Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.light-mode.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.rtl.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.rtl.png new file mode 100644 index 000000000..2a17960c4 Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railChips_default.rtl.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.dark-mode.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.dark-mode.png new file mode 100644 index 000000000..dd99abf7e Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.dark-mode.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.light-mode.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.light-mode.png new file mode 100644 index 000000000..fdf6dd168 Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.light-mode.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.rtl.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.rtl.png new file mode 100644 index 000000000..3a77c2ad7 Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_railWithStickyChips_default.rtl.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.dark-mode.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.dark-mode.png new file mode 100644 index 000000000..3d54df9b0 Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.dark-mode.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.light-mode.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.light-mode.png new file mode 100644 index 000000000..8da8a4dc2 Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.light-mode.png differ diff --git a/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.rtl.png b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.rtl.png new file mode 100644 index 000000000..f944cb48c Binary files /dev/null and b/Backpack-SwiftUI/Tests/ChipGroup/__Snapshots__/BPKChipGroupTests/test_multipleSelect_wrapChips_onDark.rtl.png differ diff --git a/Example/Backpack.xcodeproj/project.pbxproj b/Example/Backpack.xcodeproj/project.pbxproj index 579de46bd..47c1b5f9f 100644 --- a/Example/Backpack.xcodeproj/project.pbxproj +++ b/Example/Backpack.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ 3A7D2D47214AB9F400ECBD5B /* BPKButtonsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A7D2D46214AB9F400ECBD5B /* BPKButtonsViewController.m */; }; 3AA018EF215BE26600838FBB /* SpinnersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA018EE215BE26500838FBB /* SpinnersViewController.swift */; }; 3AA018F4215D000700838FBB /* TextViewsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA018F3215D000700838FBB /* TextViewsViewController.swift */; }; + 534624382A7429080059A0B5 /* ChipGroupMultipleSelectWrapExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534624372A7429080059A0B5 /* ChipGroupMultipleSelectWrapExampleView.swift */; }; + 5346243A2A74292D0059A0B5 /* ChipGroupMultipleSelectRailExampleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 534624392A74292D0059A0B5 /* ChipGroupMultipleSelectRailExampleView.swift */; }; 537ED1AF282D65A300032105 /* ShadowTokensView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 537ED1AE282D65A300032105 /* ShadowTokensView.swift */; }; 5390DB5D29098CE400F0F790 /* RadiusTokensViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5390DB5C29098CE400F0F790 /* RadiusTokensViewController.swift */; }; 5390DB5F29098D7300F0F790 /* SpacingTokensViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5390DB5E29098D7300F0F790 /* SpacingTokensViewController.swift */; }; @@ -219,6 +221,8 @@ 3AA018F3215D000700838FBB /* TextViewsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewsViewController.swift; sourceTree = ""; }; 3DDD5D1DB6A77816BAA9481F /* Pods-Backpack-Native.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Backpack-Native.release.xcconfig"; path = "Pods/Target Support Files/Pods-Backpack-Native/Pods-Backpack-Native.release.xcconfig"; sourceTree = ""; }; 455FB6E0E01310446E946427 /* Backpack.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Backpack.podspec; path = ../Backpack.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 534624372A7429080059A0B5 /* ChipGroupMultipleSelectWrapExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipGroupMultipleSelectWrapExampleView.swift; sourceTree = ""; }; + 534624392A74292D0059A0B5 /* ChipGroupMultipleSelectRailExampleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChipGroupMultipleSelectRailExampleView.swift; sourceTree = ""; }; 537ED1AE282D65A300032105 /* ShadowTokensView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShadowTokensView.swift; sourceTree = ""; }; 5390DB5C29098CE400F0F790 /* RadiusTokensViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadiusTokensViewController.swift; sourceTree = ""; }; 5390DB5E29098D7300F0F790 /* SpacingTokensViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpacingTokensViewController.swift; sourceTree = ""; }; @@ -463,6 +467,15 @@ path = Select; sourceTree = ""; }; + 5346243B2A7433040059A0B5 /* MultiSelect */ = { + isa = PBXGroup; + children = ( + 534624372A7429080059A0B5 /* ChipGroupMultipleSelectWrapExampleView.swift */, + 534624392A74292D0059A0B5 /* ChipGroupMultipleSelectRailExampleView.swift */, + ); + path = MultiSelect; + sourceTree = ""; + }; 5390DB5B29098CD700F0F790 /* Tokens */ = { isa = PBXGroup; children = ( @@ -1162,6 +1175,7 @@ A1B2DBFF2A43077E00DE6980 /* ChipGroup */ = { isa = PBXGroup; children = ( + 5346243B2A7433040059A0B5 /* MultiSelect */, 53C7F0B42A4C615D003A8740 /* SingleSelect */, ); path = ChipGroup; @@ -1572,6 +1586,7 @@ 53C6622729EA0DAB00BF1A62 /* DialogExampleView.swift in Sources */, D28784922250FCBD00353E32 /* Settings.swift in Sources */, 794337A9283C77BD00797D1C /* TabsViewController.swift in Sources */, + 5346243A2A74292D0059A0B5 /* ChipGroupMultipleSelectRailExampleView.swift in Sources */, D270C066243B61C60036A040 /* TabBarControllerStoryViewController.swift in Sources */, 7940D38D29EEB63500330480 /* StarRatingGroupsProvider.swift in Sources */, D6391600202CAAC8006E8329 /* BPKShadowViewController.m in Sources */, @@ -1657,6 +1672,7 @@ D643B6DE2142C36C008AB669 /* GradientViewController.swift in Sources */, 17068B8A299C0106000EA7F4 /* RatingGroupsProvider.swift in Sources */, 7904384A29F11EA8006CD8E0 /* SliderGroups.swift in Sources */, + 534624382A7429080059A0B5 /* ChipGroupMultipleSelectWrapExampleView.swift in Sources */, AAF235DA298BF788003D8507 /* PageIndicatorViewController.swift in Sources */, 53C6621429EA0DAB00BF1A62 /* FlareExampleView.swift in Sources */, AA7CFD8C29965EE20023C12B /* PriceExampleViewController.swift in Sources */, diff --git a/Example/Backpack/SwiftUI/Components/ChipGroup/MultiSelect/ChipGroupMultipleSelectRailExampleView.swift b/Example/Backpack/SwiftUI/Components/ChipGroup/MultiSelect/ChipGroupMultipleSelectRailExampleView.swift new file mode 100644 index 000000000..ddf579c5f --- /dev/null +++ b/Example/Backpack/SwiftUI/Components/ChipGroup/MultiSelect/ChipGroupMultipleSelectRailExampleView.swift @@ -0,0 +1,95 @@ +// +/* + * Backpack - Skyscanner's Design System + * + * Copyright © 2023 Skyscanner Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SwiftUI +import Backpack_SwiftUI + +struct ChipGroupMultipleSelectRailExampleView: View { + struct ChipData { + let name: String + var selected: Bool + } + + @State var chipsData = [ + ChipData(name: "Shenzhen", selected: false), + ChipData(name: "London", selected: false), + ChipData(name: "Edinburgh", selected: false), + ChipData(name: "Manchester", selected: false), + ChipData(name: "Belfast", selected: false), + ChipData(name: "Glasgow", selected: false) + ] + + var chips: [BPKMultiSelectChipGroup.ChipItem] { + chipsData.enumerated().map({ (index, chip) in + BPKMultiSelectChipGroup.ChipItem( + text: chip.name, selected: chip.selected, onClick: { chipsData[index].selected.toggle() } + ) + }) + } + + var body: some View { + VStack { + defaultChip + onDarkChip + onImageChip + } + .padding() + } + + var stickyChip: BPKMultiSelectChipGroup.StickyChipItem { + BPKMultiSelectChipGroup.StickyChipItem( + accessibilityLabel: "Filter", + icon: .filter, + selected: chipsData.allSatisfy(\.selected), + onClick: {} + ) + } + + var defaultChip: some View { + BPKMultiSelectChipGroup( + chips: chips, + type: .rail(stickyChip: stickyChip) + ) + .padding() + } + + var onDarkChip: some View { + BPKMultiSelectChipGroup( + chips: chips, + style: .onDark, + type: .rail(stickyChip: stickyChip)) + .padding() + .background(.surfaceContrastColor) + } + + var onImageChip: some View { + BPKMultiSelectChipGroup( + chips: chips, + style: .onImage, + type: .rail(stickyChip: stickyChip)) + .padding() + .background(.statusSuccessSpotColor) + } +} + +struct ChipGroupMultipleSelectRailExampleView_Previews: PreviewProvider { + static var previews: some View { + ChipGroupMultipleSelectRailExampleView() + } +} diff --git a/Example/Backpack/SwiftUI/Components/ChipGroup/MultiSelect/ChipGroupMultipleSelectWrapExampleView.swift b/Example/Backpack/SwiftUI/Components/ChipGroup/MultiSelect/ChipGroupMultipleSelectWrapExampleView.swift new file mode 100644 index 000000000..a0212ab74 --- /dev/null +++ b/Example/Backpack/SwiftUI/Components/ChipGroup/MultiSelect/ChipGroupMultipleSelectWrapExampleView.swift @@ -0,0 +1,86 @@ +// +/* + * Backpack - Skyscanner's Design System + * + * Copyright © 2023 Skyscanner Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import SwiftUI +import Backpack_SwiftUI + +struct ChipGroupMultipleSelectWrapExampleView: View { + struct ChipData { + let name: String + var selected: Bool + } + + @State var chipsData = [ + ChipData(name: "Shenzhen", selected: false), + ChipData(name: "London", selected: false), + ChipData(name: "Edinburgh", selected: false), + ChipData(name: "Manchester", selected: false), + ChipData(name: "Belfast", selected: false), + ChipData(name: "Glasgow", selected: false) + ] + + var chips: [BPKMultiSelectChipGroup.ChipItem] { + chipsData.enumerated().map({ (index, chip) in + BPKMultiSelectChipGroup.ChipItem( + text: chip.name, selected: chip.selected, onClick: { chipsData[index].selected.toggle() } + ) + }) + } + + var body: some View { + VStack { + defaultChip + onDarkChip + onImageChip + } + .padding() + } + + var defaultChip: some View { + BPKMultiSelectChipGroup( + chips: chips, + type: .wrap + ) + .padding() + } + + var onDarkChip: some View { + BPKMultiSelectChipGroup( + chips: chips, + style: .onDark, + type: .wrap) + .padding() + .background(.surfaceContrastColor) + } + + var onImageChip: some View { + BPKMultiSelectChipGroup( + chips: chips, + style: .onImage, + type: .wrap) + .padding() + .background(.statusSuccessSpotColor) + } +} + +struct ChipGroupMultipleSelectWrapExampleView_Previews: PreviewProvider { + static var previews: some View { + ChipGroupMultipleSelectWrapExampleView() + } +} diff --git a/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectRailExampleView.swift b/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectRailExampleView.swift index 03a451571..b00ae5e7f 100644 --- a/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectRailExampleView.swift +++ b/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectRailExampleView.swift @@ -19,6 +19,7 @@ import SwiftUI import Backpack_SwiftUI +import MapKit struct ChipGroupSingleSelectRailExampleView: View { @State var selectedChip: Int? @@ -61,13 +62,20 @@ struct ChipGroupSingleSelectRailExampleView: View { } var onImageChip: some View { - BPKSingleSelectChipGroup( - chips: chips, - style: .onImage, - selectedIndex: $selectedChip, - type: .rail) { _ in } - .padding() - .background(.statusSuccessSpotColor) + ZStack { + let coordsRegion = MKCoordinateRegion( + center: .init(latitude: 36.7, longitude: -04.4), + span: .init(latitudeDelta: 0.5, longitudeDelta: 0.5) + ) + Map(coordinateRegion: .constant(coordsRegion)) + .frame(height: 100) + BPKSingleSelectChipGroup( + chips: chips, + style: .onImage, + selectedIndex: $selectedChip, + type: .rail) { _ in } + .padding() + } } } struct ChipGroupSingleSelectRailExampleView_Previews: PreviewProvider { diff --git a/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectWrapExampleView.swift b/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectWrapExampleView.swift index 034ec9439..81ecf79b2 100644 --- a/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectWrapExampleView.swift +++ b/Example/Backpack/SwiftUI/Components/ChipGroup/SingleSelect/ChipGroupSingleSelectWrapExampleView.swift @@ -19,6 +19,7 @@ import SwiftUI import Backpack_SwiftUI +import MapKit struct ChipGroupSingleSelectWrapExampleView: View { @State var selectedChip: Int? @@ -61,13 +62,20 @@ struct ChipGroupSingleSelectWrapExampleView: View { } var onImageChip: some View { - BPKSingleSelectChipGroup( - chips: chips, - style: .onImage, - selectedIndex: $selectedChip, - type: .wrap) { _ in } - .padding() - .background(.statusSuccessSpotColor) + ZStack { + let coordsRegion = MKCoordinateRegion( + center: .init(latitude: 36.7, longitude: -04.4), + span: .init(latitudeDelta: 0.5, longitudeDelta: 0.5) + ) + Map(coordinateRegion: .constant(coordsRegion)) + .frame(height: 150) + BPKSingleSelectChipGroup( + chips: chips, + style: .onImage, + selectedIndex: $selectedChip, + type: .wrap) { _ in } + .padding() + } } } diff --git a/Example/Backpack/Utils/FeatureStories/Groups/ChipGroupProvider.swift b/Example/Backpack/Utils/FeatureStories/Groups/ChipGroupProvider.swift index 9d8fa846b..aa80ae7f6 100644 --- a/Example/Backpack/Utils/FeatureStories/Groups/ChipGroupProvider.swift +++ b/Example/Backpack/Utils/FeatureStories/Groups/ChipGroupProvider.swift @@ -40,7 +40,9 @@ struct ChipGroupProvider { SingleGroupProvider( cellDataSources: [ presentable("Rail - Single Select", view: ChipGroupSingleSelectRailExampleView()), - presentable("Wrap - Single Select", view: ChipGroupSingleSelectWrapExampleView()) + presentable("Wrap - Single Select", view: ChipGroupSingleSelectWrapExampleView()), + presentable("Rail - Multi Select", view: ChipGroupMultipleSelectRailExampleView()), + presentable("Wrap - Multi Select", view: ChipGroupMultipleSelectWrapExampleView()) ] ).groups() } diff --git a/screenshots/iPhone-swiftui_chip-group___rail_dm.png b/screenshots/iPhone-swiftui_chip-group___rail_dm.png index 28e74661b..0b9706067 100644 Binary files a/screenshots/iPhone-swiftui_chip-group___rail_dm.png and b/screenshots/iPhone-swiftui_chip-group___rail_dm.png differ diff --git a/screenshots/iPhone-swiftui_chip-group___rail_lm.png b/screenshots/iPhone-swiftui_chip-group___rail_lm.png index 337101e8b..7fb00868e 100644 Binary files a/screenshots/iPhone-swiftui_chip-group___rail_lm.png and b/screenshots/iPhone-swiftui_chip-group___rail_lm.png differ diff --git a/screenshots/iPhone-swiftui_chip-group___wrap_dm.png b/screenshots/iPhone-swiftui_chip-group___wrap_dm.png index f0e28e6ef..f62796187 100644 Binary files a/screenshots/iPhone-swiftui_chip-group___wrap_dm.png and b/screenshots/iPhone-swiftui_chip-group___wrap_dm.png differ diff --git a/screenshots/iPhone-swiftui_chip-group___wrap_lm.png b/screenshots/iPhone-swiftui_chip-group___wrap_lm.png index bf2fced5c..f228f2fed 100644 Binary files a/screenshots/iPhone-swiftui_chip-group___wrap_lm.png and b/screenshots/iPhone-swiftui_chip-group___wrap_lm.png differ