Sources/Source/Components/PaginationProgressBar.swift (88 lines of code) (raw):
import SwiftUI
#if os(iOS)
/// This component used to signpost progression through a paginated view.
///
/// On tablet, buttons are provided to allow users to navigate through the pages.
public struct PaginationProgressBar: View {
private let pageCount: Int
private let indicatorWidth: CGFloat
private let primaryColor: Color
private let secondaryColor: Color
@Binding private var selectedIndex: Int
@Environment(\.horizontalSizeClass)
private var sizeClass
@State private var canNavigateBack = true
@State private var canNavigateForward = false
public init(
pageCount: Int,
indicatorWidth: CGFloat,
selectedIndex: Binding<Int>,
primaryColor: Color,
secondaryColor: Color
) {
self.pageCount = pageCount
self.indicatorWidth = indicatorWidth
self._selectedIndex = selectedIndex
self.primaryColor = primaryColor
self.secondaryColor = secondaryColor
}
private var forwardEnabled: Bool {
return selectedIndex < pageCount - 1
}
public var body: some View {
Group {
if sizeClass == .regular {
ZStack(alignment: .trailing) {
scrollingIndicator
.frame(maxWidth: .infinity, alignment: .center)
PaginationButtons(iconColor: primaryColor, borderColor: secondaryColor, selectedIndex: $selectedIndex, canNavigateForward: forwardEnabled)
.frame(alignment: .trailing)
}
} else {
scrollingIndicator
}
}
.onChange(of: selectedIndex) { selectedIndex in
updateButtonDisabledState()
}
}
private var scrollingIndicator: some View {
ScrollingPaginationIndicator(
pageCount: pageCount,
indicatorWidth: indicatorWidth,
selectedIndex: $selectedIndex,
primaryColor: primaryColor,
secondaryColor: secondaryColor
)
}
private func updateButtonDisabledState() {
canNavigateBack = selectedIndex == 0
canNavigateForward = selectedIndex == pageCount - 1
}
}
struct PaginationProgressBar_Previews_Container: PreviewProvider {
struct Container: View {
@State var selectedIndex: Int = 0
let elementArray = [0, 1, 2, 3, 4, 5, 6]
var body: some View {
VStack {
TabView(selection: $selectedIndex) {
ForEach(elementArray, id: \.self) { index in
Text("\(index)")
.font(.largeTitle)
}
}
.tabViewStyle(.page(indexDisplayMode: .never))
PaginationProgressBar(
pageCount: elementArray.count,
indicatorWidth: 16,
selectedIndex: $selectedIndex,
primaryColor: Color(uiColor: ColorPalette.neutral0),
secondaryColor: Color(uiColor: ColorPalette.neutral73)
)
.padding()
}
}
}
static var previews: some View {
Container()
}
}
#endif