diff --git a/README.md b/README.md
index f06fc42b..31e10f04 100644
--- a/README.md
+++ b/README.md
@@ -841,6 +841,178 @@ shopify.addEventListener('geolocationRequest', async (event: GeolocationRequestE
---
+## Accelerated Checkouts
+
+Accelerated checkout buttons surface Apple Pay and Shop Pay options earlier in the buyer journey so more orders complete without leaving your app.
+
+### Prerequisites
+
+- iOS 16 or later
+- The `write_cart_wallet_payments` access scope ([request access](https://www.appsheet.com/start/1ff317b6-2da1-4f39-b041-c01cfada6098))
+- Apple Pay payment processing certificates ([setup guide](https://shopify.dev/docs/storefronts/mobile/create-apple-payment-processing-certificates))
+- A device configured for Apple Pay ([Apple setup instructions](https://developer.apple.com/documentation/passkit/setting-up-apple-pay))
+
+### Configure the integration
+
+Pass an `acceleratedCheckouts` configuration when setting up the provider or `ShopifyCheckoutSheet` instance. This connects the accelerated checkout buttons to your storefront.
+
+```tsx
+import {ShopifyCheckoutSheetProvider} from '@shopify/checkout-sheet-kit';
+
+const config = {
+ acceleratedCheckouts: {
+ storefrontDomain: 'your-shop.myshopify.com',
+ storefrontAccessToken: 'your-storefront-access-token',
+ customer: {
+ // For authenticated customers
+ accessToken: 'customer-access-token',
+ // OR for guest customers
+ // email: 'customer@example.com',
+ // phoneNumber: '0123456789',
+ },
+ wallets: {
+ applePay: {
+ merchantIdentifier: 'merchant.com.yourcompany',
+ contactFields: ['email', 'phone'],
+ // Optionally restrict shipping countries (ISO 3166-1 alpha-2)
+ // supportedShippingCountries: ['US', 'CA'],
+ },
+ },
+ },
+};
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+> [!WARNING]
+> Do not provide both `accessToken` and `email`/`phoneNumber` together. For authenticated customers, email and phone are fetched automatically from the Shopify account.
+
+### Render accelerated checkout buttons
+
+Use `AcceleratedCheckoutButtons` to attach accelerated checkout calls-to-action to product or cart surfaces once you have a valid cart ID or product variant ID from the Storefront API.
+
+```tsx
+import {
+ AcceleratedCheckoutButtons,
+ AcceleratedCheckoutWallet,
+} from '@shopify/checkout-sheet-kit';
+
+function CartFooter({cartId}: {cartId: string}) {
+ return (
+
+ );
+}
+```
+
+You can also render buttons for a single product variant:
+
+```tsx
+
+```
+
+#### Customize wallet options
+
+Accelerated checkout buttons display every available wallet by default. Use `wallets` to show a subset or adjust the order.
+
+```tsx
+// Display only Shop Pay
+
+
+// Display Shop Pay first, then Apple Pay
+
+```
+
+#### Modify the Apple Pay button label
+
+Use `applePayLabel` to map to the native `PayWithApplePayButtonLabel` values. The default is `plain`.
+
+```tsx
+import {ApplePayLabel} from '@shopify/checkout-sheet-kit';
+
+
+```
+
+#### Customize the Apple Pay button style
+
+Use `applePayStyle` to set the color style of the Apple Pay button. The default is `automatic`, which adapts to the current appearance (light/dark mode).
+
+```tsx
+import {ApplePayStyle} from '@shopify/checkout-sheet-kit';
+
+
+```
+
+Available styles: `automatic`, `black`, `white`, `whiteOutline`.
+
+#### Customize button corners
+
+The `cornerRadius` prop lets you match the buttons to other calls-to-action in your app. Buttons default to an 8pt radius.
+
+```tsx
+// Pill-shaped buttons
+
+
+// Square buttons
+
+```
+
+### Handle loading, errors, and lifecycle events
+
+Attach lifecycle handlers to respond when buyers finish, cancel, or encounter an error.
+
+```tsx
+ {
+ // Clear cart after successful checkout
+ clearCart();
+ }}
+ onFail={(error) => {
+ console.error('Accelerated checkout failed:', error);
+ }}
+ onCancel={() => {
+ analytics.track('accelerated_checkout_cancelled');
+ }}
+ onRenderStateChange={(event) => {
+ // event.state: 'loading' | 'rendered' | 'error'
+ setRenderState(event.state);
+ }}
+ onWebPixelEvent={(event) => {
+ analytics.track(event);
+ }}
+ onClickLink={(url) => {
+ Linking.openURL(url);
+ }}
+/>
+```
+
+---
+
## Contributing
See the [contributing documentation](CONTRIBUTING.md) for details on how to get started.
diff --git a/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec b/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec
index 99c25f14..092b4913 100644
--- a/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec
+++ b/modules/@shopify/checkout-sheet-kit/RNShopifyCheckoutSheetKit.podspec
@@ -20,8 +20,8 @@ Pod::Spec.new do |s|
s.source_files = "ios/*.{h,m,mm,swift}"
s.dependency "React-Core"
- s.dependency "ShopifyCheckoutSheetKit", "~> 3.7.0"
- s.dependency "ShopifyCheckoutSheetKit/AcceleratedCheckouts", "~> 3.7.0"
+ s.dependency "ShopifyCheckoutSheetKit", "~> 3.8.0"
+ s.dependency "ShopifyCheckoutSheetKit/AcceleratedCheckouts", "~> 3.8.0"
if fabric_enabled
# Use React Native's helper if available, otherwise add dependencies directly
diff --git a/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons+Extensions.swift b/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons+Extensions.swift
index 9e4c4df4..cddc7f6c 100644
--- a/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons+Extensions.swift
+++ b/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons+Extensions.swift
@@ -58,3 +58,23 @@ extension PayWithApplePayButtonLabel {
"topUp": .topUp
]
}
+
+// MARK: - Apple Pay Button Style
+
+@available(iOS 16.0, *)
+extension PayWithApplePayButtonStyle {
+ static func from(_ string: String?, fallback: PayWithApplePayButtonStyle = .automatic) -> PayWithApplePayButtonStyle {
+ guard let string, let value = map[string] else {
+ return fallback
+ }
+
+ return value
+ }
+
+ private static let map: [String: PayWithApplePayButtonStyle] = [
+ "automatic": .automatic,
+ "black": .black,
+ "white": .white,
+ "whiteOutline": .whiteOutline
+ ]
+}
diff --git a/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons.swift b/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons.swift
index 75a78b72..fcefb67c 100644
--- a/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons.swift
+++ b/modules/@shopify/checkout-sheet-kit/ios/AcceleratedCheckoutButtons.swift
@@ -120,6 +120,12 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
}
}
+ @objc var applePayStyle: String? {
+ didSet {
+ updateView()
+ }
+ }
+
@objc var onFail: RCTBubblingEventBlock?
@objc var onComplete: RCTBubblingEventBlock?
@objc var onCancel: RCTBubblingEventBlock?
@@ -156,6 +162,17 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
hostingController?.view.frame = bounds
}
+ // Deprecated in iOS 17 — superseded by registerForTraitChanges in setupView().
+ // Remove this override when dropping iOS 16 support.
+ override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
+ super.traitCollectionDidChange(previousTraitCollection)
+ if #unavailable(iOS 17.0) {
+ if traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
+ updateView()
+ }
+ }
+ }
+
override var intrinsicContentSize: CGSize {
let height = calculateRequiredHeight()
return CGSize(width: UIView.noIntrinsicMetric, height: height)
@@ -172,6 +189,14 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
updateView()
+ // Replaces traitCollectionDidChange for iOS 17+.
+ // When dropping iOS 16 support, remove the traitCollectionDidChange override above.
+ if #available(iOS 17.0, *) {
+ registerForTraitChanges([UITraitUserInterfaceStyle.self]) { [weak self] (_: RCTAcceleratedCheckoutButtonsView, _: UITraitCollection) in
+ self?.updateView()
+ }
+ }
+
// Listen for configuration updates
NotificationCenter.default.addObserver(
self,
@@ -207,7 +232,7 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
updateView()
}
- private func attachModifiers(to buttons: AcceleratedCheckoutButtons, wallets: [Wallet]?, applePayLabel: PayWithApplePayButtonLabel?) -> AcceleratedCheckoutButtons {
+ private func attachModifiers(to buttons: AcceleratedCheckoutButtons, wallets: [Wallet]?, applePayLabel: PayWithApplePayButtonLabel?, applePayStyle: PayWithApplePayButtonStyle) -> AcceleratedCheckoutButtons {
var modifiedButtons = buttons
if let wallets {
@@ -218,6 +243,8 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
modifiedButtons = modifiedButtons.applePayLabel(applePayLabel)
}
+ modifiedButtons = modifiedButtons.applePayStyle(applePayStyle)
+
if let cornerRadius {
modifiedButtons = modifiedButtons.cornerRadius(CGFloat(cornerRadius.doubleValue))
}
@@ -276,18 +303,20 @@ class RCTAcceleratedCheckoutButtonsView: UIView {
return
}
- // Attach modifiers (wallets, applePayLabel, cornerRadius)
- buttons = attachModifiers(to: buttons, wallets: shopifyWallets, applePayLabel: PayWithApplePayButtonLabel.from(applePayLabel))
+ // Attach modifiers (wallets, applePayLabel, applePayStyle, cornerRadius)
+ buttons = attachModifiers(to: buttons, wallets: shopifyWallets, applePayLabel: PayWithApplePayButtonLabel.from(applePayLabel), applePayStyle: PayWithApplePayButtonStyle.from(applePayStyle))
// Attach event handlers
buttons = attachEventListeners(to: buttons)
var view: AnyView
+ let colorScheme: SwiftUI.ColorScheme = traitCollection.userInterfaceStyle == .dark ? .dark : .light
+
// Attach config (and Apple Pay config if available)
if let applePayConfig = AcceleratedCheckoutConfiguration.shared.applePayConfiguration {
- view = AnyView(buttons.environmentObject(config).environmentObject(applePayConfig))
+ view = AnyView(buttons.environmentObject(config).environmentObject(applePayConfig).environment(\.colorScheme, colorScheme))
} else {
- view = AnyView(buttons.environmentObject(config))
+ view = AnyView(buttons.environmentObject(config).environment(\.colorScheme, colorScheme))
}
if let hostingController {
diff --git a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm
index 2971cd2c..5a3d7017 100644
--- a/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm
+++ b/modules/@shopify/checkout-sheet-kit/ios/ShopifyCheckoutSheetKit.mm
@@ -106,6 +106,11 @@ @interface RCT_EXTERN_MODULE (RCTAcceleratedCheckoutButtonsManager, RCTViewManag
*/
RCT_EXPORT_VIEW_PROPERTY(applePayLabel, NSString*)
+/**
+ * Style variant for the Apple Pay button (e.g., "automatic", "black", "white", "whiteOutline").
+ */
+RCT_EXPORT_VIEW_PROPERTY(applePayStyle, NSString*)
+
/**
* Emitted when checkout fails. Payload contains a CheckoutException-like shape.
*/
diff --git a/modules/@shopify/checkout-sheet-kit/package.json b/modules/@shopify/checkout-sheet-kit/package.json
index efd4b641..3ddaf0de 100644
--- a/modules/@shopify/checkout-sheet-kit/package.json
+++ b/modules/@shopify/checkout-sheet-kit/package.json
@@ -1,7 +1,7 @@
{
"name": "@shopify/checkout-sheet-kit",
"license": "MIT",
- "version": "3.7.0",
+ "version": "3.8.0",
"main": "lib/commonjs/index.js",
"types": "src/index.ts",
"source": "src/index.ts",
diff --git a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx
index 7958fe85..ab8971f7 100644
--- a/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx
+++ b/modules/@shopify/checkout-sheet-kit/src/components/AcceleratedCheckoutButtons.tsx
@@ -61,6 +61,13 @@ export enum ApplePayLabel {
topUp = 'topUp',
}
+export enum ApplePayStyle {
+ automatic = 'automatic',
+ black = 'black',
+ white = 'white',
+ whiteOutline = 'whiteOutline',
+}
+
type CheckoutIdentifier =
| {
cartId: string;
@@ -87,6 +94,12 @@ interface CommonAcceleratedCheckoutButtonsProps {
*/
applePayLabel?: ApplePayLabel;
+ /**
+ * Style for the Apple Pay button color
+ * Defaults to 'automatic' which adapts to the current appearance (light/dark mode)
+ */
+ applePayStyle?: ApplePayStyle;
+
/**
* Called when checkout fails
*/
@@ -148,6 +161,7 @@ export type AcceleratedCheckoutButtonsProps = (CartProps | VariantProps) &
interface NativeAcceleratedCheckoutButtonsProps {
applePayLabel?: string;
+ applePayStyle?: string;
style?: ViewStyle;
checkoutIdentifier: CheckoutIdentifier;
cornerRadius?: number;
@@ -193,6 +207,7 @@ export const AcceleratedCheckoutButtons: React.FC<
AcceleratedCheckoutButtonsProps
> = ({
applePayLabel,
+ applePayStyle,
cornerRadius,
wallets,
onFail,
@@ -307,6 +322,7 @@ export const AcceleratedCheckoutButtons: React.FC<
return (
3.7.0)
- - ShopifyCheckoutSheetKit/AcceleratedCheckouts (~> 3.7.0)
+ - ShopifyCheckoutSheetKit (~> 3.8.0)
+ - ShopifyCheckoutSheetKit/AcceleratedCheckouts (~> 3.8.0)
- SocketRocket
- Yoga
- RNVectorIcons (10.3.0):
@@ -2638,11 +2638,11 @@ PODS:
- ReactCommon/turbomodule/core
- SocketRocket
- Yoga
- - ShopifyCheckoutSheetKit (3.7.0):
- - ShopifyCheckoutSheetKit/Core (= 3.7.0)
- - ShopifyCheckoutSheetKit/AcceleratedCheckouts (3.7.0):
+ - ShopifyCheckoutSheetKit (3.8.0):
+ - ShopifyCheckoutSheetKit/Core (= 3.8.0)
+ - ShopifyCheckoutSheetKit/AcceleratedCheckouts (3.8.0):
- ShopifyCheckoutSheetKit/Core
- - ShopifyCheckoutSheetKit/Core (3.7.0)
+ - ShopifyCheckoutSheetKit/Core (3.8.0)
- SocketRocket (0.7.1)
- Yoga (0.0.0)
@@ -2996,9 +2996,9 @@ SPEC CHECKSUMS:
RNGestureHandler: eeb622199ef1fb3a076243131095df1c797072f0
RNReanimated: 288616f9c66ff4b0911f3862ffcf4104482a2adc
RNScreens: 3fc29af06302e1f1c18a7829fe57cbc2c0259912
- RNShopifyCheckoutSheetKit: 979ca69f1abbd0b38c3e996879e77a5b42a0103a
+ RNShopifyCheckoutSheetKit: 5587e0fc360607d832f7f10f8436883d1db4b5ef
RNVectorIcons: be4d047a76ad307ffe54732208fb0498fcb8477f
- ShopifyCheckoutSheetKit: 5bdc6c6c0dafc5ef15daa5963c03547bf6bfff6a
+ ShopifyCheckoutSheetKit: 5253ca4da4c4f31069286509693930d02b4150d8
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: a742cc68e8366fcfc681808162492bc0aa7a9498
diff --git a/sample/src/context/Config.tsx b/sample/src/context/Config.tsx
index a92d6296..407fde01 100644
--- a/sample/src/context/Config.tsx
+++ b/sample/src/context/Config.tsx
@@ -6,7 +6,7 @@ import React, {
useMemo,
useState,
} from 'react';
-import {ColorScheme} from '@shopify/checkout-sheet-kit';
+import {ColorScheme, ApplePayStyle} from '@shopify/checkout-sheet-kit';
import EncryptedStorage from 'react-native-encrypted-storage';
import {useTheme} from './Theme';
import {BuyerIdentityMode} from '../auth/types';
@@ -14,6 +14,7 @@ import {BuyerIdentityMode} from '../auth/types';
export interface AppConfig {
colorScheme: ColorScheme;
buyerIdentityMode: BuyerIdentityMode;
+ applePayStyle?: ApplePayStyle;
}
interface Context {
@@ -26,6 +27,7 @@ const CONFIG_STORAGE_KEY = 'app_config';
const defaultAppConfig: AppConfig = {
colorScheme: ColorScheme.automatic,
buyerIdentityMode: BuyerIdentityMode.Guest,
+ applePayStyle: ApplePayStyle.automatic,
};
const ConfigContext = createContext({
diff --git a/sample/src/screens/CartScreen.tsx b/sample/src/screens/CartScreen.tsx
index 54e828bc..e5712df3 100644
--- a/sample/src/screens/CartScreen.tsx
+++ b/sample/src/screens/CartScreen.tsx
@@ -41,6 +41,7 @@ import {
ApplePayLabel,
AcceleratedCheckoutWallet,
} from '@shopify/checkout-sheet-kit';
+import {useConfig} from '../context/Config';
import useShopify from '../hooks/useShopify';
import type {CartLineItem} from '../../@types';
import type {Colors} from '../context/Theme';
@@ -55,6 +56,7 @@ function CartScreen(): React.JSX.Element {
const {cartId, checkoutURL, totalQuantity, removeFromCart, addingToCart} =
useCart();
const {queries} = useShopify();
+ const {appConfig} = useConfig();
const eventHandlers = useShopifyEventHandlers(
'Cart - AcceleratedCheckoutButtons',
);
@@ -167,6 +169,7 @@ function CartScreen(): React.JSX.Element {
;
@@ -90,6 +91,7 @@ function ProductDetails({
loading?: boolean;
onAddToCart: (variantId: string) => void;
}) {
+ const {appConfig} = useConfig();
const {colors, cornerRadius} = useTheme();
const styles = createStyles(colors, cornerRadius);
const image = product.images?.edges[0]?.node;
@@ -126,6 +128,7 @@ function ProductDetails({
{
+ setAppConfig({
+ ...appConfig,
+ applePayStyle: item.value as ApplePayStyle,
+ });
+ },
+ [appConfig, setAppConfig],
+ );
+
const handleBuyerIdentityModeChange = useCallback(
(item: SingleSelectItem) => {
const newMode = item.value as BuyerIdentityMode;
@@ -200,6 +211,27 @@ function SettingsScreen() {
[appConfig.colorScheme],
);
+ const applePayStyleDisplayNames: Record = useMemo(
+ () => ({
+ [ApplePayStyle.automatic]: 'Automatic',
+ [ApplePayStyle.black]: 'Black',
+ [ApplePayStyle.white]: 'White',
+ [ApplePayStyle.whiteOutline]: 'White Outline',
+ }),
+ [],
+ );
+
+ const applePayStyleOptions: readonly SingleSelectItem[] = useMemo(
+ () =>
+ Object.values(ApplePayStyle).map(style => ({
+ title: applePayStyleDisplayNames[style],
+ type: SectionType.SingleSelect as const,
+ value: style,
+ selected: appConfig.applePayStyle === style,
+ })),
+ [appConfig.applePayStyle, applePayStyleDisplayNames],
+ );
+
const informationalItems: readonly TextItem[] = useMemo(
() => [
{
@@ -237,6 +269,12 @@ function SettingsScreen() {
title: 'Theme',
data: themeOptions,
},
+ {
+ title: 'Apple Pay Style',
+ footer:
+ 'Configures the visual style of the Apple Pay button.',
+ data: applePayStyleOptions,
+ },
{
title: 'Versions',
data: informationalItems,
@@ -246,6 +284,7 @@ function SettingsScreen() {
themeOptions,
configurationOptions,
buyerIdentityOptions,
+ applePayStyleOptions,
informationalItems,
],
);
@@ -263,16 +302,16 @@ function SettingsScreen() {
}
if (isSingleSelectItem(item)) {
- const isAuthSection = section.title === 'Authentication';
+ const sectionHandlers: Record void> = {
+ Authentication: handleBuyerIdentityModeChange,
+ 'Apple Pay Style': handleApplePayStyleChange,
+ };
+ const handler = sectionHandlers[section.title] ?? handleColorSchemeChange;
return (
- isAuthSection
- ? handleBuyerIdentityModeChange(item)
- : handleColorSchemeChange(item)
- }
+ onPress={() => handler(item)}
/>
);
}