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

Lmn 25/multiselect chip group #1717

Merged
merged 4 commits into from
Jul 31, 2023
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
208 changes: 208 additions & 0 deletions Backpack-SwiftUI/ChipGroup/Classes/BPKMultiSelectChipGroup.swift
Original file line number Diff line number Diff line change
@@ -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) {
anambl marked this conversation as resolved.
Show resolved Hide resolved
if let stickyChip {
BPKStickyChip(stickyChip: stickyChip, style: style)
Color(BPKColor.lineColor)
anambl marked this conversation as resolved.
Show resolved Hide resolved
.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..<chips.count, id: \.self) { index in
chip(for: chips[index])
}
}

@ViewBuilder
private func chip(for chip: ChipItem) -> 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(
anambl marked this conversation as resolved.
Show resolved Hide resolved
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 {
anambl marked this conversation as resolved.
Show resolved Hide resolved
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)
}
}
}
41 changes: 41 additions & 0 deletions Backpack-SwiftUI/ChipGroup/Classes/BPKStickyChip.swift
Original file line number Diff line number Diff line change
@@ -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)
}
}
94 changes: 76 additions & 18 deletions Backpack-SwiftUI/ChipGroup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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
)
```
Loading
Loading