Skip to content

Commit 045bb00

Browse files
committed
Create POS button style with filled/outlined variant, normal/extraSmall size, and disabled state.
1 parent 3163247 commit 045bb00

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import SwiftUI
2+
3+
/// The visual variant of the POS button.
4+
enum POSButtonVariant {
5+
case filled
6+
case outlined
7+
}
8+
9+
/// The size variant of the POS button.
10+
enum POSButtonSize {
11+
case normal
12+
case extraSmall
13+
}
14+
15+
/// A unified button style for POS that supports different variants and sizes.
16+
struct POSButtonStyle: ButtonStyle {
17+
@Environment(\.colorScheme) var colorScheme
18+
@Environment(\.isEnabled) var isEnabled
19+
20+
let variant: POSButtonVariant
21+
let size: POSButtonSize
22+
23+
init(variant: POSButtonVariant = .filled,
24+
size: POSButtonSize = .normal) {
25+
self.variant = variant
26+
self.size = size
27+
}
28+
29+
func makeBody(configuration: Configuration) -> some View {
30+
HStack {
31+
Spacer()
32+
configuration.label
33+
Spacer()
34+
}
35+
.padding(.vertical, size.padding.vertical)
36+
.padding(.horizontal, size.padding.horizontal)
37+
.font(size.font)
38+
.background(backgroundColor)
39+
.foregroundColor(foregroundColor)
40+
.overlay(borderOverlay)
41+
.cornerRadius(POSButtonStyleConstants.framedButtonCornerRadius)
42+
}
43+
44+
private var backgroundColor: Color {
45+
switch (variant, isEnabled) {
46+
case (.filled, true):
47+
.posPrimaryContainer
48+
case (.filled, false):
49+
.posDisabledContainer
50+
case (.outlined, _):
51+
.clear
52+
}
53+
}
54+
55+
private var foregroundColor: Color {
56+
switch (variant, isEnabled) {
57+
case (.filled, true):
58+
.posOnPrimaryContainer
59+
case (.filled, false):
60+
.posOnDisabledContainer
61+
case (.outlined, true):
62+
.posOnSurface
63+
case (.outlined, false):
64+
.posOnDisabledContainer
65+
}
66+
}
67+
68+
@ViewBuilder
69+
private var borderOverlay: some View {
70+
if variant == .outlined {
71+
RoundedRectangle(cornerRadius: POSButtonStyleConstants.framedButtonCornerRadius)
72+
.stroke(isEnabled ? Color.posInverseSurface : .posDisabledContainer,
73+
lineWidth: 2)
74+
}
75+
}
76+
}
77+
78+
// MARK: - POSButtonSize Extensions
79+
80+
private extension POSButtonSize {
81+
var padding: (vertical: CGFloat, horizontal: CGFloat) {
82+
switch self {
83+
case .normal:
84+
(vertical: 24, horizontal: 24)
85+
case .extraSmall:
86+
(vertical: 8, horizontal: 16)
87+
}
88+
}
89+
90+
var font: POSFontStyle {
91+
switch self {
92+
case .normal:
93+
.posBodyEmphasized
94+
case .extraSmall:
95+
.posDetailEmphasized
96+
}
97+
}
98+
}
99+
100+
// MARK: - Preview
101+
102+
#if DEBUG
103+
104+
struct POSButtonStyle_Previews: View {
105+
var body: some View {
106+
ScrollView {
107+
VStack(alignment: .leading, spacing: 32) {
108+
previewSection(title: "Filled Buttons - Normal",
109+
variant: .filled, size: .normal)
110+
111+
previewSection(title: "Filled Buttons - Extra Small",
112+
variant: .filled, size: .extraSmall)
113+
114+
previewSection(title: "Outlined Buttons - Normal",
115+
variant: .outlined, size: .normal)
116+
117+
previewSection(title: "Outlined Buttons - Extra Small",
118+
variant: .outlined, size: .extraSmall)
119+
120+
// Example with long text
121+
VStack(alignment: .leading, spacing: 16) {
122+
Text("Long Text Examples")
123+
.font(.headline)
124+
125+
Button("This is a very long button text that might wrap to multiple lines") {}
126+
.buttonStyle(POSButtonStyle(variant: .filled, size: .normal))
127+
128+
Button("Long text in small size button that might need to wrap") {}
129+
.buttonStyle(POSButtonStyle(variant: .outlined, size: .extraSmall))
130+
}
131+
}
132+
.padding()
133+
}
134+
}
135+
136+
private func previewSection(title: String, variant: POSButtonVariant, size: POSButtonSize) -> some View {
137+
VStack(alignment: .leading, spacing: 16) {
138+
Text(title)
139+
.font(.headline)
140+
141+
Button("Enabled Button") {}
142+
.buttonStyle(POSButtonStyle(variant: variant, size: size))
143+
144+
Button("Disabled Button") {}
145+
.buttonStyle(POSButtonStyle(variant: variant, size: size))
146+
.disabled(true)
147+
}
148+
}
149+
}
150+
151+
#Preview("Button Styles") {
152+
POSButtonStyle_Previews()
153+
}
154+
155+
#endif

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@
118118
021080FA2D5441CE0054C78D /* POSColorPalette.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 021080F92D5441CE0054C78D /* POSColorPalette.xcassets */; };
119119
021080FC2D544B3E0054C78D /* Color+POSColorPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = 021080FB2D544B3E0054C78D /* Color+POSColorPalette.swift */; };
120120
0210A2472D55EC250054C78D /* POSButtonStylesPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0210A2462D55EC250054C78D /* POSButtonStylesPreview.swift */; };
121+
0210A2492D55F0530054C78D /* POSButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0210A2482D55F0530054C78D /* POSButtonStyle.swift */; };
121122
0210D8692A7BEEF700846F8C /* WooAnalyticsEvent+ProductListFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0210D8682A7BEEF700846F8C /* WooAnalyticsEvent+ProductListFilter.swift */; };
122123
0211252825773F220075AD2A /* Models+Copiable.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0211252725773F220075AD2A /* Models+Copiable.generated.swift */; };
123124
0211252E25773FB00075AD2A /* MockAggregateOrderItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0211252D25773FB00075AD2A /* MockAggregateOrderItem.swift */; };
@@ -3327,6 +3328,7 @@
33273328
021080F92D5441CE0054C78D /* POSColorPalette.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = POSColorPalette.xcassets; sourceTree = "<group>"; };
33283329
021080FB2D544B3E0054C78D /* Color+POSColorPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+POSColorPalette.swift"; sourceTree = "<group>"; };
33293330
0210A2462D55EC250054C78D /* POSButtonStylesPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSButtonStylesPreview.swift; sourceTree = "<group>"; };
3331+
0210A2482D55F0530054C78D /* POSButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSButtonStyle.swift; sourceTree = "<group>"; };
33303332
0210D8682A7BEEF700846F8C /* WooAnalyticsEvent+ProductListFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WooAnalyticsEvent+ProductListFilter.swift"; sourceTree = "<group>"; };
33313333
0211252725773F220075AD2A /* Models+Copiable.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Models+Copiable.generated.swift"; sourceTree = "<group>"; };
33323334
0211252D25773FB00075AD2A /* MockAggregateOrderItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAggregateOrderItem.swift; sourceTree = "<group>"; };
@@ -6656,6 +6658,7 @@
66566658
0210A2452D55EC140054C78D /* Buttons */ = {
66576659
isa = PBXGroup;
66586660
children = (
6661+
0210A2482D55F0530054C78D /* POSButtonStyle.swift */,
66596662
0210A2462D55EC250054C78D /* POSButtonStylesPreview.swift */,
66606663
);
66616664
path = Buttons;
@@ -16284,6 +16287,7 @@
1628416287
CE2DF92E2CC16C95001AA394 /* WooShippingServiceCardView.swift in Sources */,
1628516288
0247F512286F73EA009C177E /* WooAnalyticsEvent+ImageUpload.swift in Sources */,
1628616289
202D2A5A2AC5933100E4ABC0 /* TopTabView.swift in Sources */,
16290+
0210A2492D55F0530054C78D /* POSButtonStyle.swift in Sources */,
1628716291
B57C744A20F5649300EEFC87 /* EmptyStoresTableViewCell.swift in Sources */,
1628816292
45DB70602614C7E80064A6CF /* ShippingLabelPackageDetailsResultsControllers.swift in Sources */,
1628916293
B9F148982AD5541C008FC795 /* AddCustomAmountViewModel.swift in Sources */,

0 commit comments

Comments
 (0)