Skip to content

Commit 2203733

Browse files
committed
Make tab indicator slide when switched
1 parent e0e9329 commit 2203733

File tree

1 file changed

+37
-17
lines changed

1 file changed

+37
-17
lines changed

WooCommerce/Classes/Bookings/BookingList/BookingListView.swift

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,28 +75,33 @@ private extension BookingListView {
7575
}
7676

7777
var topTabView: some View {
78-
HStack {
79-
ForEach(Array(tabs.enumerated()), id: \.element) { (index, title) in
80-
Button {
81-
selectedTabIndex = index
82-
} label: {
83-
Text(title)
84-
.font(.subheadline)
85-
.foregroundStyle(selectedTabIndex == index ? Color.accentColor : Color.primary)
86-
}
87-
.frame(maxWidth: .infinity)
88-
.padding(.vertical, 12)
89-
.overlay {
90-
VStack {
91-
Spacer()
92-
if selectedTabIndex == index {
93-
Color.accentColor
94-
.frame(height: Layout.selectedTabIndicatorHeight)
78+
GeometryReader { geometry in
79+
HStack {
80+
ForEach(Array(tabs.enumerated()), id: \.element) { (index, title) in
81+
Button {
82+
withAnimation(.easeInOut(duration: 0.3)) {
83+
selectedTabIndex = index
9584
}
85+
} label: {
86+
Text(title)
87+
.font(.subheadline)
88+
.foregroundStyle(selectedTabIndex == index ? Color.accentColor : Color.primary)
9689
}
90+
.frame(maxWidth: .infinity)
91+
.padding(.vertical, 12)
9792
}
9893
}
94+
.overlay(alignment: .bottom) {
95+
Color.accentColor
96+
.frame(width: geometry.size.width / CGFloat(tabs.count),
97+
height: Layout.selectedTabIndicatorHeight)
98+
.offset(x: tabIndicatorOffset(containerWidth: geometry.size.width,
99+
tabCount: tabs.count,
100+
selectedIndex: selectedTabIndex))
101+
.animation(.easeInOut(duration: 0.3), value: selectedTabIndex)
102+
}
99103
}
104+
.frame(height: Layout.topTabBarHeight)
100105
.background(Color(.listForeground(modal: false)))
101106
}
102107

@@ -165,10 +170,25 @@ private extension BookingListView {
165170
.padding(.vertical, 4)
166171
.background(color.clipShape(RoundedRectangle(cornerRadius: 4)))
167172
}
173+
174+
/// SwiftUI's coordinate system places (0,0) at the center of the container, so we need to:
175+
/// 1. Calculate how far the selected tab is from the left edge
176+
/// 2. Adjust for the center-based coordinate system
177+
/// 3. Center the indicator within the selected tab
178+
///
179+
func tabIndicatorOffset(containerWidth: CGFloat, tabCount: Int, selectedIndex: Int) -> CGFloat {
180+
let tabWidth = containerWidth / CGFloat(tabCount)
181+
let distanceFromLeftEdge = tabWidth * CGFloat(selectedIndex)
182+
let adjustmentForCenterOrigin = containerWidth / 2
183+
let centerWithinTab = tabWidth / 2
184+
185+
return distanceFromLeftEdge - adjustmentForCenterOrigin + centerWithinTab
186+
}
168187
}
169188
private extension BookingListView {
170189
enum Layout {
171190
static let viewPadding: CGFloat = 16
191+
static let topTabBarHeight: CGFloat = 44
172192
static let selectedTabIndicatorHeight: CGFloat = 3.0
173193
static let defaultBadgeColor = Color(uiColor: .init(light: .systemGray6, dark: .systemGray5))
174194
}

0 commit comments

Comments
 (0)