Skip to content

Commit 905753e

Browse files
committed
Add success state to POSButtonStyle
1 parent 5eb08d6 commit 905753e

File tree

1 file changed

+72
-12
lines changed

1 file changed

+72
-12
lines changed

WooCommerce/Classes/POS/Presentation/Reusable Views/Buttons/POSButtonStyle.swift

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,31 @@ enum POSButtonSize {
66
case extraSmall
77
}
88

9-
/// Filled button style in POS that can show a loading indicator.
9+
/// Button state for different visual presentations
10+
enum POSButtonState {
11+
case idle
12+
case loading
13+
case success
14+
}
15+
16+
/// Filled button style in POS that can show loading and success states.
1017
struct POSFilledButtonStyle: ButtonStyle {
1118
private let size: POSButtonSize
12-
private let isLoading: Bool
19+
private let state: POSButtonState
1320

1421
init(size: POSButtonSize, isLoading: Bool = false) {
1522
self.size = size
16-
self.isLoading = isLoading
23+
self.state = isLoading ? .loading : .idle
24+
}
25+
26+
init(size: POSButtonSize, state: POSButtonState) {
27+
self.size = size
28+
self.state = state
1729
}
1830

1931
func makeBody(configuration: Configuration) -> some View {
20-
POSButton(configuration: configuration, variant: .filled, size: size, isLoading: isLoading)
32+
POSButtonStyleInternal(configuration: configuration, variant: .filled, size: size, state: state)
33+
.disabled(state != .idle)
2134
}
2235
}
2336

@@ -30,32 +43,35 @@ struct POSOutlinedButtonStyle: ButtonStyle {
3043
}
3144

3245
func makeBody(configuration: Configuration) -> some View {
33-
POSButton(configuration: configuration, variant: .outlined, size: size, isLoading: false)
46+
POSButtonStyleInternal(configuration: configuration, variant: .outlined, size: size, state: .idle)
3447
}
3548
}
3649

50+
3751
/// The visual variant of the POS button.
3852
fileprivate enum POSButtonVariant {
3953
case filled
4054
case outlined
4155
}
4256

43-
private struct POSButton: View {
57+
private struct POSButtonStyleInternal: View {
4458
@Environment(\.isEnabled) var isEnabled
4559

4660
let configuration: ButtonStyleConfiguration
4761
let variant: POSButtonVariant
4862
let size: POSButtonSize
49-
let isLoading: Bool
63+
let state: POSButtonState
5064

5165
var body: some View {
5266
Group {
5367
containerView {
5468
ZStack(alignment: .center) {
5569
configuration.label
56-
.opacity(isLoading ? 0 : 1)
70+
.opacity(state == .idle ? 1 : 0)
5771
progressView
58-
.renderedIf(isLoading)
72+
.renderedIf(state == .loading)
73+
successView
74+
.renderedIf(state == .success)
5975
}
6076
}
6177
}
@@ -91,12 +107,18 @@ private struct POSButton: View {
91107
.progressViewStyle(POSButtonProgressViewStyle(size: size.progressViewDimensions.size, lineWidth: size.progressViewDimensions.lineWidth))
92108
}
93109

110+
private var successView: some View {
111+
Image(systemName: "checkmark.circle")
112+
.font(size == .normal ? .title2 : .body)
113+
.foregroundColor(.posOnPrimaryContainer)
114+
}
115+
94116
private var backgroundColor: Color {
95117
switch (variant, isEnabled) {
96118
case (.filled, true):
97119
.posPrimaryContainer
98120
case (.filled, false):
99-
isLoading ? .posPrimaryContainer : .posDisabledContainer
121+
state != .idle ? .posPrimaryContainer : .posDisabledContainer
100122
case (.outlined, _):
101123
.clear
102124
}
@@ -125,9 +147,9 @@ private struct POSButton: View {
125147
}
126148
}
127149

128-
// MARK: - POSButton Constants
150+
// MARK: - POSButtonStyleInternal Constants
129151

130-
private extension POSButton {
152+
private extension POSButtonStyleInternal {
131153
enum Constants {
132154
static let cornerRadius: CGFloat = POSCornerRadiusStyle.medium.value
133155
static let borderStrokeWidth: CGFloat = 2.0
@@ -190,6 +212,10 @@ struct POSButtonStyle_Previews: View {
190212
LoadingPreviewSection(title: "Loading Buttons - Normal", size: .normal)
191213

192214
LoadingPreviewSection(title: "Loading Buttons - Extra Small", size: .extraSmall)
215+
216+
LoadingStatePreviewSection(title: "Loading State Buttons - Normal", size: .normal)
217+
218+
LoadingStatePreviewSection(title: "Loading State Buttons - Extra Small", size: .extraSmall)
193219

194220
// Example with long text
195221
VStack(alignment: .leading, spacing: POSSpacing.medium) {
@@ -262,6 +288,40 @@ private struct LoadingPreviewSection: View {
262288
}
263289
}
264290

291+
private struct LoadingStatePreviewSection: View {
292+
let title: String
293+
let size: POSButtonSize
294+
@State private var currentState: POSButtonState = .idle
295+
296+
var body: some View {
297+
VStack(alignment: .leading, spacing: POSSpacing.medium) {
298+
Text(title)
299+
.font(.headline)
300+
301+
Button("Cycle States") {
302+
switch currentState {
303+
case .idle:
304+
currentState = .loading
305+
case .loading:
306+
currentState = .success
307+
case .success:
308+
currentState = .idle
309+
}
310+
}
311+
.buttonStyle(POSFilledButtonStyle(size: size, state: currentState))
312+
313+
Button("Idle State") {}
314+
.buttonStyle(POSFilledButtonStyle(size: size, state: .idle))
315+
316+
Button("Loading State") {}
317+
.buttonStyle(POSFilledButtonStyle(size: size, state: .loading))
318+
319+
Button("Success State") {}
320+
.buttonStyle(POSFilledButtonStyle(size: size, state: .success))
321+
}
322+
}
323+
}
324+
265325
#Preview("Button Styles") {
266326
POSButtonStyle_Previews()
267327
}

0 commit comments

Comments
 (0)