Skip to content

Commit

Permalink
Merge pull request #1938 from Skyscanner/bellagio/horizontal_navigation
Browse files Browse the repository at this point in the history
Refactor BPKHorizontalNavigation to include onClick handlers for tab selection
  • Loading branch information
frugoman authored Apr 15, 2024
2 parents fb75bd5 + 91ced04 commit affca0a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,36 +41,43 @@ public extension BPKHorizontalNavigation {
struct Tab {
let title: String
let icon: BPKIcon?

public init(title: String, icon: BPKIcon? = nil) {
let onClick: () -> Void

public init(
title: String,
icon: BPKIcon? = nil,
onClick: @escaping () -> Void
) {
self.title = title
self.icon = icon
self.onClick = onClick
}
}
}

public struct BPKHorizontalNavigation: View {
let tabs: [Tab]
let size: Size
@Binding var selectedTab: Int
let selectedTab: Int

public init(tabs: [Tab], size: Size = .default, selectedTab: Binding<Int>) {
public init(
tabs: [Tab],
size: Size = .default,
selectedTab: Int
) {
self.tabs = tabs
self.size = size
_selectedTab = selectedTab
self.selectedTab = selectedTab
}

public var body: some View {
ZStack(alignment: .bottom) {
HStack(spacing: BPKSpacing.none) {
ForEach(0..<tabs.count, id: \.self) { index in
Button {
withAnimation {
selectedTab = index
}
} label: {
let tab = tabs[index]
Button(action: tab.onClick) {
TabCellView(
tab: tabs[index],
tab: tab,
isSelected: selectedTab == index,
size: size
)
Expand All @@ -83,6 +90,7 @@ public struct BPKHorizontalNavigation: View {
let width = tabsWidth(for: proxy)
Color(.coreAccentColor)
.frame(width: width)
.animation(.default, value: selectedTab)
.offset(x: width * CGFloat(selectedTab))
}
.frame(height: 2)
Expand Down Expand Up @@ -119,32 +127,34 @@ public struct BPKHorizontalNavigation: View {

struct BPKHorizontalNavigation_Previews: PreviewProvider {
static var previews: some View {
let titleTabs: [BPKHorizontalNavigation.Tab] = [
.init(title: "One", onClick: {}),
.init(title: "Two", onClick: {}),
.init(title: "Three", onClick: {})
]
let titleAndIconTabs: [BPKHorizontalNavigation.Tab] = [
.init(title: "One", icon: .flight, onClick: {}),
.init(title: "Two", icon: .flight, onClick: {}),
.init(title: "Three", icon: .flight, onClick: {})
]
VStack {
BPKHorizontalNavigation(
tabs: [.init(title: "One"), .init(title: "Two"), .init(title: "Three")],
selectedTab: .constant(1)
tabs: titleTabs,
selectedTab: 1
)
BPKHorizontalNavigation(
tabs: [
.init(title: "One", icon: .flight),
.init(title: "Two", icon: .flight),
.init(title: "Three", icon: .flight)
],
selectedTab: .constant(1)
tabs: titleAndIconTabs,
selectedTab: 1
)
BPKHorizontalNavigation(
tabs: [.init(title: "One"), .init(title: "Two"), .init(title: "Three")],
tabs: titleTabs,
size: .small,
selectedTab: .constant(2)
selectedTab: 2
)
BPKHorizontalNavigation(
tabs: [
.init(title: "One", icon: .flight),
.init(title: "Two", icon: .flight),
.init(title: "Three", icon: .flight)
],
tabs: titleAndIconTabs,
size: .small,
selectedTab: .constant(0)
selectedTab: 0
)
}
}
Expand Down
24 changes: 12 additions & 12 deletions Backpack-SwiftUI/HorizontalNavigation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
@State var selectedTab: Int = 0
BPKHorizontalNavigation(
tabs: [
.init(title: "Flights", icon: .flight),
.init(title: "Hotels", icon: .hotel),
.init(title: "Cars", icon: .car)
.init(title: "Flights", icon: .flight, onClick: { selectedTab = 0 }),
.init(title: "Hotels", icon: .hotel, onClick: { selectedTab = 1 }),
.init(title: "Cars", icon: .car, onClick: { selectedTab = 2 }),
],
selectedTab: $selectedTab
selectedTab: selectedTab
)
```

Expand All @@ -32,12 +32,12 @@ BPkHorizontalNavigation supports both a `default` and a `small` size.
@State var selectedTab: Int = 0
BPKHorizontalNavigation(
tabs: [
.init(title: "Flights", icon: .flight),
.init(title: "Hotels", icon: .hotel),
.init(title: "Cars", icon: .car)
.init(title: "Flights", icon: .flight, onClick: { selectedTab = 0 }),
.init(title: "Hotels", icon: .hotel, onClick: { selectedTab = 1 }),
.init(title: "Cars", icon: .car, onClick: { selectedTab = 2 }),
],
size: .small,
selectedTab: $selectedTab
selectedTab: selectedTab
)
```

Expand All @@ -47,10 +47,10 @@ BPKHorizontalNavigation(
@State var selectedTab: Int = 0
BPKHorizontalNavigation(
tabs: [
.init(title: "Flights"),
.init(title: "Hotels"),
.init(title: "Cars")
.init(title: "Flights", onClick: { selectedTab = 0 }),
.init(title: "Hotels", onClick: { selectedTab = 1 }),
.init(title: "Cars", onClick: { selectedTab = 2 }),
],
selectedTab: $selectedTab
selectedTab: selectedTab
)
```
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class BPKHorizontalNavigationTests: XCTestCase {
assertSnapshot(
BPKHorizontalNavigation(
tabs: [.init(title: "One"), .init(title: "Two"), .init(title: "Three")],
selectedTab: .constant(1)
selectedTab: 1
)
.frame(width: 400)
)
Expand All @@ -36,7 +36,7 @@ class BPKHorizontalNavigationTests: XCTestCase {
BPKHorizontalNavigation(
tabs: [.init(title: "One"), .init(title: "Two"), .init(title: "Three")],
size: .small,
selectedTab: .constant(1)
selectedTab: 1
)
.frame(width: 400)
)
Expand All @@ -50,7 +50,7 @@ class BPKHorizontalNavigationTests: XCTestCase {
.init(title: "Two", icon: .flight),
.init(title: "Three", icon: .flight)
],
selectedTab: .constant(1)
selectedTab: 1
)
.frame(width: 400)
)
Expand All @@ -65,7 +65,7 @@ class BPKHorizontalNavigationTests: XCTestCase {
.init(title: "Three", icon: .flight)
],
size: .small,
selectedTab: .constant(1)
selectedTab: 1
)
.frame(width: 400)
)
Expand All @@ -79,8 +79,14 @@ class BPKHorizontalNavigationTests: XCTestCase {
.init(title: "Two", icon: .flight),
.init(title: "Three", icon: .flight)
],
selectedTab: .constant(1)
selectedTab: 1
)
)
}
}

extension BPKHorizontalNavigation.Tab {
init(title: String, icon: BPKIcon? = nil) {
self.init(title: title, icon: icon, onClick: {})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,32 @@ struct HorizontalNavigationExampleView: View {

var body: some View {
VStack {
BPKHorizontalNavigation(
tabs: [.init(title: "One"), .init(title: "Two"), .init(title: "Three")],
selectedTab: $selectedTab
)
components(size: .default)
components(size: .small)
}
}

private func components(
size: Backpack_SwiftUI.BPKHorizontalNavigation.Size
) -> some View {
VStack {
BPKHorizontalNavigation(
tabs: [
.init(title: "One", icon: .flight),
.init(title: "Two", icon: .flight),
.init(title: "Three", icon: .flight)
.init(title: "One", onClick: { selectedTab = 0 }),
.init(title: "Two", onClick: { selectedTab = 1 }),
.init(title: "Three", onClick: { selectedTab = 2 })
],
selectedTab: $selectedTab
)
BPKHorizontalNavigation(
tabs: [.init(title: "One"), .init(title: "Two"), .init(title: "Three")],
size: .small,
selectedTab: $selectedTab
size: size,
selectedTab: selectedTab
)
BPKHorizontalNavigation(
tabs: [
.init(title: "One", icon: .flight),
.init(title: "Two", icon: .flight),
.init(title: "Three", icon: .flight)
.init(title: "One", icon: .flight, onClick: { selectedTab = 0 }),
.init(title: "Two", icon: .flight, onClick: { selectedTab = 1 }),
.init(title: "Three", icon: .flight, onClick: { selectedTab = 2 })
],
size: .small,
selectedTab: $selectedTab
size: size,
selectedTab: selectedTab
)
}
}
Expand Down

0 comments on commit affca0a

Please sign in to comment.