Skip to content

Commit 040606e

Browse files
Add customizable corner radius to accelerated checkout buttons (#331)
* feat: add customizable corner radius to accelerated checkout buttons - Add withCornerRadius() modifier to AcceleratedCheckoutButtons - Make corner radius configurable in ShopPayButton and ApplePayButton - Default to 8pt radius, with negative values falling back to default - Update sample app to demonstrate corner radius customization * refactor: rename withCornerRadius to cornerRadius for SwiftUI consistency - Rename public API method from withCornerRadius to cornerRadius - Update documentation example to use new method name - Update test method names to match new API - Update sample app usage to use new method name This change aligns the API with SwiftUI naming conventions where view modifiers typically don't use 'with' prefix.
1 parent a09ce31 commit 040606e

File tree

7 files changed

+91
-17
lines changed

7 files changed

+91
-17
lines changed

Samples/ShopifyAcceleratedCheckoutsApp/ShopifyAcceleratedCheckoutsApp/Views/Components/ButtonSet.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,12 @@ struct ButtonSet: View {
6262
let productVariant = merchandise.asProductVariant
6363
{
6464
CheckoutSection(title: "AcceleratedCheckoutButtons(variantID: quantity:)") {
65-
// Variant-based checkout with separate handlers
65+
// Variant-based checkout with separate handlers and custom corner radius
6666
AcceleratedCheckoutButtons(
6767
variantID: productVariant.id,
6868
quantity: firstVariantQuantity
6969
)
70+
.cornerRadius(24)
7071
.withWallets([.applepay, .shoppay])
7172
.onComplete {
7273
print("✅ Variant checkout completed")

Sources/ShopifyAcceleratedCheckouts/Wallets/AcceleratedCheckoutButtons.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public struct AcceleratedCheckoutButtons: View {
3939
let identifier: CheckoutIdentifier
4040
var wallets: [Wallet] = [.shoppay, .applepay]
4141
var eventHandlers: EventHandlers = .init()
42+
var cornerRadius: CGFloat?
4243

4344
@State private var shopSettings: ShopSettings?
4445

@@ -69,12 +70,14 @@ public struct AcceleratedCheckoutButtons: View {
6970
case .applepay:
7071
ApplePayButton(
7172
identifier: identifier,
72-
eventHandlers: eventHandlers
73+
eventHandlers: eventHandlers,
74+
cornerRadius: cornerRadius
7375
)
7476
case .shoppay:
7577
ShopPayButton(
7678
identifier: identifier,
77-
eventHandlers: eventHandlers
79+
eventHandlers: eventHandlers,
80+
cornerRadius: cornerRadius
7881
)
7982
}
8083
}
@@ -110,6 +113,23 @@ extension AcceleratedCheckoutButtons {
110113
return newView
111114
}
112115

116+
/// Sets the corner radius for all checkout buttons
117+
///
118+
/// Use this modifier to customize the corner radius of the buttons:
119+
///
120+
/// ```swift
121+
/// AcceleratedCheckoutButtons(cartID: cartId)
122+
/// .cornerRadius(12)
123+
/// ```
124+
///
125+
/// - Parameter radius: The corner radius to apply to all buttons (default: 8). Negative values will use the default.
126+
/// - Returns: A view with the custom corner radius applied
127+
public func cornerRadius(_ radius: CGFloat) -> AcceleratedCheckoutButtons {
128+
var newView = self
129+
newView.cornerRadius = radius
130+
return newView
131+
}
132+
113133
/// Adds an action to perform when the checkout completes successfully.
114134
///
115135
/// Use this modifier to handle successful checkout events:

Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayButton.swift

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,17 @@ struct ApplePayButton: View {
4949
/// The Apple Pay button label style
5050
private var label: PayWithApplePayButtonLabel = .plain
5151

52+
/// The corner radius for the button
53+
private let cornerRadius: CGFloat?
54+
5255
public init(
5356
identifier: CheckoutIdentifier,
54-
eventHandlers: EventHandlers = EventHandlers()
57+
eventHandlers: EventHandlers = EventHandlers(),
58+
cornerRadius: CGFloat?
5559
) {
5660
self.identifier = identifier.parse()
5761
self.eventHandlers = eventHandlers
62+
self.cornerRadius = cornerRadius
5863
}
5964

6065
var body: some View {
@@ -69,7 +74,8 @@ struct ApplePayButton: View {
6974
common: configuration, applePay: applePayConfiguration,
7075
shopSettings: shopSettings
7176
),
72-
eventHandlers: eventHandlers
77+
eventHandlers: eventHandlers,
78+
cornerRadius: cornerRadius
7379
)
7480
}
7581
}
@@ -92,6 +98,9 @@ struct Internal_ApplePayButton: View {
9298
/// The view controller for the Apple Pay button
9399
private var controller: ApplePayViewController
94100

101+
/// The corner radius for the button
102+
private let cornerRadius: CGFloat?
103+
95104
/// Initializes an Apple Pay button
96105
/// - Parameters:
97106
/// - identifier: The identifier to use for checkout
@@ -102,12 +111,15 @@ struct Internal_ApplePayButton: View {
102111
identifier: CheckoutIdentifier,
103112
label: PayWithApplePayButtonLabel,
104113
configuration: ApplePayConfigurationWrapper,
105-
eventHandlers: EventHandlers = EventHandlers()
114+
eventHandlers: EventHandlers = EventHandlers(),
115+
cornerRadius: CGFloat?
106116
) {
107117
controller = ApplePayViewController(
108118
identifier: identifier,
109119
configuration: configuration
110120
)
121+
self.label = label
122+
self.cornerRadius = cornerRadius
111123
MainActor.assumeIsolated {
112124
controller.onComplete = eventHandlers.checkoutDidComplete
113125
controller.onFail = eventHandlers.checkoutDidFail
@@ -116,7 +128,6 @@ struct Internal_ApplePayButton: View {
116128
controller.onClickLink = eventHandlers.checkoutDidClickLink
117129
controller.onWebPixelEvent = eventHandlers.checkoutDidEmitWebPixelEvent
118130
}
119-
self.label = label
120131
}
121132

122133
var body: some View {
@@ -130,6 +141,6 @@ struct Internal_ApplePayButton: View {
130141
Text("errors.applepay.unsupported".localizedString)
131142
}
132143
)
133-
.walletButtonStyle()
144+
.walletButtonStyle(cornerRadius: cornerRadius)
134145
}
135146
}

Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayButton.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,16 @@ internal struct ShopPayButton: View {
3131

3232
let identifier: CheckoutIdentifier
3333
let eventHandlers: EventHandlers
34+
let cornerRadius: CGFloat?
3435

3536
init(
3637
identifier: CheckoutIdentifier,
37-
eventHandlers: EventHandlers = EventHandlers()
38+
eventHandlers: EventHandlers = EventHandlers(),
39+
cornerRadius: CGFloat?
3840
) {
3941
self.identifier = identifier.parse()
4042
self.eventHandlers = eventHandlers
43+
self.cornerRadius = cornerRadius
4144
}
4245

4346
var body: some View {
@@ -48,7 +51,8 @@ internal struct ShopPayButton: View {
4851
Internal_ShopPayButton(
4952
identifier: identifier,
5053
configuration: configuration,
51-
eventHandlers: eventHandlers
54+
eventHandlers: eventHandlers,
55+
cornerRadius: cornerRadius
5256
)
5357
}
5458
}
@@ -59,17 +63,20 @@ internal struct ShopPayButton: View {
5963
@available(iOS 17.0, *)
6064
internal struct Internal_ShopPayButton: View {
6165
private var controller: ShopPayViewController
66+
private let cornerRadius: CGFloat?
6267

6368
init(
6469
identifier: CheckoutIdentifier,
6570
configuration: ShopifyAcceleratedCheckouts.Configuration,
66-
eventHandlers: EventHandlers = EventHandlers()
71+
eventHandlers: EventHandlers = EventHandlers(),
72+
cornerRadius: CGFloat?
6773
) {
6874
controller = ShopPayViewController(
6975
identifier: identifier,
7076
configuration: configuration,
7177
eventHandlers: eventHandlers
7278
)
79+
self.cornerRadius = cornerRadius
7380
}
7481

7582
var body: some View {
@@ -90,7 +97,7 @@ internal struct Internal_ShopPayButton: View {
9097
.background(Color.shopPayBlue)
9198
}
9299
)
93-
.walletButtonStyle(bg: Color.shopPayBlue)
100+
.walletButtonStyle(bg: Color.shopPayBlue, cornerRadius: cornerRadius)
94101
.buttonStyle(ContentFadeButtonStyle())
95102
}
96103
}

Sources/ShopifyAcceleratedCheckouts/Wallets/Wallet.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ public struct EventHandlers {
5757
}
5858

5959
extension View {
60-
func walletButtonStyle(bg: Color = Color.black) -> some View {
61-
frame(height: 48)
60+
func walletButtonStyle(bg: Color = Color.black, cornerRadius: CGFloat? = nil) -> some View {
61+
let defaultCornerRadius: CGFloat = 8
62+
let radius = cornerRadius ?? defaultCornerRadius
63+
return frame(height: 48)
6264
.background(bg)
63-
.clipShape(RoundedRectangle(cornerRadius: 8))
65+
.clipShape(RoundedRectangle(cornerRadius: radius >= 0 ? radius : defaultCornerRadius))
6466
}
6567
}
6668

Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayIntegrationTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ final class ApplePayIntegrationTests: XCTestCase {
143143
func testInvariantIdentifierHandling() {
144144
let identifier = CheckoutIdentifier.invariant
145145

146-
let button = ApplePayButton(identifier: identifier, eventHandlers: EventHandlers())
146+
let button = ApplePayButton(identifier: identifier, eventHandlers: EventHandlers(), cornerRadius: nil)
147147

148148
// Create hosting controller to render the view
149149
let hostingController = UIHostingController(
@@ -165,7 +165,8 @@ final class ApplePayIntegrationTests: XCTestCase {
165165

166166
let button = ApplePayButton(
167167
identifier: .cart(cartID: "gid://Shopify/Cart/test-cart"),
168-
eventHandlers: EventHandlers(checkoutDidComplete: successHandler)
168+
eventHandlers: EventHandlers(checkoutDidComplete: successHandler),
169+
cornerRadius: nil
169170
)
170171

171172
// Apply additional modifiers (simulating view updates)

Tests/ShopifyAcceleratedCheckoutsTests/Wallets/ApplePay/ApplePayViewModifierTests.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,38 @@ final class ApplePayViewModifierTests: XCTestCase {
303303
XCTAssertNotNil(modifiedView, "Modified view should be created successfully")
304304
}
305305

306+
// MARK: - Corner Radius Modifier Tests
307+
308+
func testCornerRadiusModifier() {
309+
let view = AcceleratedCheckoutButtons(cartID: "gid://Shopify/Cart/test-cart-id")
310+
.cornerRadius(16)
311+
.environment(mockConfiguration)
312+
.environment(mockApplePayConfiguration)
313+
.environment(mockShopSettings)
314+
315+
XCTAssertNotNil(view, "View should be created successfully with corner radius modifier")
316+
}
317+
318+
func testCornerRadiusZeroValue() {
319+
let view = AcceleratedCheckoutButtons(cartID: "gid://Shopify/Cart/test-cart-id")
320+
.cornerRadius(0)
321+
.environment(mockConfiguration)
322+
.environment(mockApplePayConfiguration)
323+
.environment(mockShopSettings)
324+
325+
XCTAssertNotNil(view, "View should be created successfully with zero corner radius")
326+
}
327+
328+
func testCornerRadiusNegativeValue() {
329+
let view = AcceleratedCheckoutButtons(cartID: "gid://Shopify/Cart/test-cart-id")
330+
.cornerRadius(-10)
331+
.environment(mockConfiguration)
332+
.environment(mockApplePayConfiguration)
333+
.environment(mockShopSettings)
334+
335+
XCTAssertNotNil(view, "View should be created successfully with negative corner radius")
336+
}
337+
306338
// MARK: - Helper Methods
307339

308340
private func extractEnvironmentValue<T>(from _: Mirror, keyPath _: KeyPath<EnvironmentValues, T>) -> T? {

0 commit comments

Comments
 (0)