Skip to content

Commit

Permalink
Merge pull request #115 from guardian/aml/separate-out-progress-buttons
Browse files Browse the repository at this point in the history
iOS - Separate out pagination button from progress bar component
  • Loading branch information
aoifemcl15 authored Oct 8, 2024
2 parents 1ee7d4a + 6dbe27d commit bf7cff2
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 48 deletions.
23 changes: 11 additions & 12 deletions Sources/Source/Components/Buttons/IconButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ public struct IconButton: View {
private let iconColor: Color
private let borderColor: Color
private let action: () -> ()
@Binding private var disabled: Bool
private var disabled: Bool

public init(
icon: Image,
size: ButtonSize,
iconColor: Color,
borderColor: Color,
disabled: Binding<Bool> = .constant(false),
disabled: Bool = false,
action: @escaping () -> Void
) {
self.icon = icon
self.size = size
self.iconColor = iconColor
self.borderColor = borderColor
self._disabled = disabled
self.disabled = disabled
self.action = action
}

Expand All @@ -35,26 +35,25 @@ public struct IconButton: View {
icon
.resizable()
}
.buttonStyle(IconButtonStyle(size: size, isDisabled: $disabled, borderColor: borderColor, iconColor: iconColor))

.buttonStyle(IconButtonStyle(size: size, isDisabled: disabled, borderColor: borderColor, iconColor: iconColor))
}
}

/// Custom button style used to style an icon button.
///
/// Custom disabled functionality has been used here, rather than the native to ensure the styling of the button in the disabled state is correctly reflected and that no touch events are passed through to the view behind.
struct IconButtonStyle: ButtonStyle {
let size: ButtonSize
@Binding private var isDisabled: Bool
let borderColor: Color
let iconColor: Color
private let size: ButtonSize
private let isDisabled: Bool
private let borderColor: Color
private let iconColor: Color

@Environment(\.colorScheme) private
var colorScheme

init(size: ButtonSize, isDisabled: Binding<Bool> = .constant(false), borderColor: Color, iconColor: Color) {
init(size: ButtonSize, isDisabled: Bool = false, borderColor: Color, iconColor: Color) {
self.size = size
self._isDisabled = isDisabled
self.isDisabled = isDisabled
self.borderColor = borderColor
self.iconColor = iconColor
}
Expand Down Expand Up @@ -82,7 +81,7 @@ struct IconButtonStyle: ButtonStyle {
}

#Preview {
IconButton(icon: Image(.chevronLeft), size: .small, iconColor: .black, borderColor: .gray, disabled: .constant(false), action: {})
IconButton(icon: Image(.chevronLeft), size: .small, iconColor: .black, borderColor: .gray, disabled: false, action: {})
}

// Maps button size to layout values for icon.
Expand Down
65 changes: 65 additions & 0 deletions Sources/Source/Components/PaginationButtons.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import SwiftUI

public struct PaginationButtons: View {
let iconColor: Color
let borderColor: Color
@Binding var selectedIndex: Int?
let pageCount: Int

public init(
iconColor: Color,
borderColor: Color,
selectedIndex: Binding<Int?>,
pageCount: Int
) {
self.iconColor = iconColor
self.borderColor = borderColor
self._selectedIndex = selectedIndex
self.pageCount = pageCount
}

private var backDisabled: Bool {
guard let selectedIndex else { return true }
return selectedIndex == 0
}

private var forwardDisabled: Bool {
guard let selectedIndex else { return true }
return selectedIndex >= pageCount - 1
}

public var body: some View {
HStack {
IconButton(
icon: Image(.chevronLeft),
size: .small,
iconColor: iconColor,
borderColor: borderColor,
disabled: backDisabled
) {
withAnimation {
if let selectedIndex {
self.selectedIndex = selectedIndex - 1
}
}
}
IconButton(
icon: Image(.chevronRight),
size: .small,
iconColor: iconColor,
borderColor: borderColor,
disabled: forwardDisabled
) {
withAnimation {
if let selectedIndex {
self.selectedIndex = selectedIndex + 1
}
}
}
}
}
}

#Preview {
PaginationButtons(iconColor: .blue, borderColor: .red, selectedIndex: .constant(0), pageCount: 10)
}
36 changes: 4 additions & 32 deletions Sources/Source/Components/PaginationProgressBar.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import SwiftUI
import Source

/// This component used to signpost progression through a paginated view.
///
Expand All @@ -8,10 +7,10 @@ public struct PaginationProgressBar: View {

private let pageCount: Int
private let indicatorWidth: CGFloat
@Binding private var selectedIndex: Int
private let primaryColor: Color
private let secondaryColor: Color

@Binding private var selectedIndex: Int?
@Environment(\.horizontalSizeClass)
private var sizeClass

Expand All @@ -22,7 +21,7 @@ public struct PaginationProgressBar: View {
public init(
pageCount: Int,
indicatorWidth: CGFloat,
selectedIndex: Binding<Int>,
selectedIndex: Binding<Int?>,
primaryColor: Color,
secondaryColor: Color
) {
Expand All @@ -39,7 +38,7 @@ public struct PaginationProgressBar: View {
ZStack(alignment: .trailing) {
scrollingIndicator
.frame(maxWidth: .infinity, alignment: .center)
progressButtons
PaginationButtons(iconColor: primaryColor, borderColor: secondaryColor, selectedIndex: $selectedIndex, pageCount: pageCount)
.frame(alignment: .trailing)
}
} else {
Expand All @@ -61,33 +60,6 @@ public struct PaginationProgressBar: View {
)
}

private var progressButtons: some View {
HStack {
IconButton(
icon: Image(.chevronLeft),
size: .small,
iconColor: primaryColor,
borderColor: secondaryColor,
disabled: $canNavigateBack
) {
withAnimation {
selectedIndex -= 1
}
}
IconButton(
icon: Image(.chevronRight),
size: .small,
iconColor: primaryColor,
borderColor: secondaryColor,
disabled: $canNavigateForward
) {
withAnimation {
selectedIndex += 1
}
}
}
}

private func updateButtonDisabledState() {
canNavigateBack = selectedIndex == 0
canNavigateForward = selectedIndex == pageCount - 1
Expand All @@ -96,7 +68,7 @@ public struct PaginationProgressBar: View {

struct PaginationProgressBar_Previews_Container: PreviewProvider {
struct Container: View {
@State var selectedIndex = 0
@State var selectedIndex: Int? = 0
let elementArray = [0, 1, 2, 3, 4, 5, 6]
var body: some View {
VStack {
Expand Down
8 changes: 4 additions & 4 deletions Sources/Source/Components/ScrollingPaginationIndicator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SwiftUI
public struct ScrollingPaginationIndicator: View {

private let pageCount: Int
@Binding private var selectedIndex: Int
@Binding private var selectedIndex: Int?
private let numberOfVisibleDots: Int
private let spacing: CGFloat
private let indicatorWidth: CGFloat
Expand Down Expand Up @@ -34,7 +34,7 @@ public struct ScrollingPaginationIndicator: View {
numberOfVisibleDots: Int = 5,
indicatorWidth: CGFloat,
spacing: CGFloat = 4,
selectedIndex: Binding<Int>,
selectedIndex: Binding<Int?>,
primaryColor: Color,
secondaryColor: Color
) {
Expand All @@ -56,7 +56,7 @@ public struct ScrollingPaginationIndicator: View {
/// - Parameter index: The index of the item for which the scale factor is to be calculated.
/// - Returns: A `CGFloat` value representing the scale factor for the item at the given index.
private func scale(for index: Int) -> CGFloat {
guard pageCount >= numberOfVisibleDots else { return 1.0 }
guard pageCount >= numberOfVisibleDots, let selectedIndex else { return 1.0 }
let indexDifference = abs(index - selectedIndex)
let scaleSpread = max((CGFloat(numberOfVisibleDots - 1) / 2 + 1), 1)
let scaleFactor = CGFloat(indexDifference) / scaleSpread
Expand Down Expand Up @@ -90,7 +90,7 @@ public struct ScrollingPaginationIndicator: View {

struct ScrollingPageIndicator_Previews_Container: PreviewProvider {
struct Container: View {
@State var selectedIndex = 0
@State var selectedIndex: Int? = 0
let elementArray = [0, 1, 2, 3, 4, 5, 6, 7, 8]
var body: some View {
VStack {
Expand Down

0 comments on commit bf7cff2

Please sign in to comment.