diff --git a/changelog/fix-show-preview-for-express-checkout-buttons-in-editor b/changelog/fix-show-preview-for-express-checkout-buttons-in-editor
new file mode 100644
index 00000000000..86092b348d7
--- /dev/null
+++ b/changelog/fix-show-preview-for-express-checkout-buttons-in-editor
@@ -0,0 +1,4 @@
+Significance: minor
+Type: fix
+
+Show Express Checkout button previews in template editor
diff --git a/client/express-checkout/blocks/components/express-checkout-button-preview.js b/client/express-checkout/blocks/components/express-checkout-button-preview.js
new file mode 100644
index 00000000000..f7103875833
--- /dev/null
+++ b/client/express-checkout/blocks/components/express-checkout-button-preview.js
@@ -0,0 +1,137 @@
+/**
+ * External dependencies
+ */
+import { useEffect, useRef } from 'react';
+
+/**
+ * Internal dependencies
+ */
+import { getExpressCheckoutButtonAppearance } from '../../utils';
+
+export const SUPPORTED_PREVIEW_PAYMENT_METHODS = [ 'googlePay', 'applePay' ];
+
+const GooglePayButtonPreview = ( { options, buttonAttributes, theme } ) => {
+ const googlePlayContainerRef = useRef( null );
+ const hasStartedLoadingGooglePlayButton = useRef( null );
+ const appearance = getExpressCheckoutButtonAppearance( buttonAttributes );
+ const borderRadius = appearance.variables.borderRadius;
+
+ useEffect( () => {
+ if (
+ googlePlayContainerRef.current &&
+ ! hasStartedLoadingGooglePlayButton.current
+ ) {
+ hasStartedLoadingGooglePlayButton.current = true;
+ ( async () => {
+ // The container may be inside an iframe, so we need to retrieve a reference to the document and window objects.
+ const targetDocument =
+ googlePlayContainerRef.current.ownerDocument;
+ const targetWindow = targetDocument.defaultView;
+ if ( ! targetWindow.google?.payments?.api?.PaymentsClient ) {
+ await new Promise( ( resolve ) => {
+ const script = document.createElement( 'script' );
+ script.src = 'https://pay.google.com/gp/p/js/pay.js';
+ script.onload = resolve;
+ targetDocument.head.appendChild( script );
+ } );
+ }
+
+ const googlePayClient = new targetWindow.google.payments.api.PaymentsClient(
+ {
+ environment: 'TEST',
+ }
+ );
+
+ const buttonColor = theme === 'black' ? 'black' : 'white'; // There is no 'outline' theme in Google Pay.
+
+ const button = googlePayClient.createButton( {
+ buttonType: options.buttonType.googlePay,
+ buttonColor,
+ buttonRadius: parseFloat( borderRadius ),
+ buttonSizeMode: 'fill',
+ onClick: () => {},
+ } );
+ googlePlayContainerRef.current.appendChild( button );
+ } )();
+ }
+ }, [ theme, borderRadius, options.buttonType.googlePay ] );
+
+ useEffect( () => {
+ googlePlayContainerRef.current
+ ?.querySelector( 'button' )
+ ?.style?.setProperty( 'border-radius', borderRadius );
+ }, [ borderRadius ] );
+
+ return (
+
+ );
+};
+
+const ApplePayButtonPreview = ( { options, buttonAttributes, theme } ) => {
+ const appearance = getExpressCheckoutButtonAppearance( buttonAttributes );
+ const borderRadius = appearance.variables.borderRadius;
+
+ const buttonStyle = {
+ height: `${ options.buttonHeight }px`,
+ borderRadius,
+ ApplePayButtonType: options.buttonType.applePay,
+ WebkitAppearance: '-apple-pay-button',
+ width: '100%',
+ };
+
+ if ( [ 'black', 'white', 'white-outline' ].includes( theme ) ) {
+ buttonStyle.ApplePayButtonStyle = theme;
+ } else {
+ buttonStyle.ApplePayButtonStyle = 'white';
+ }
+
+ return (
+
+
+
+ );
+};
+
+const ExpressCheckoutButtonPreview = ( {
+ expressPaymentMethod,
+ options,
+ buttonAttributes,
+} ) => {
+ const theme = options.buttonTheme[ expressPaymentMethod ];
+
+ if ( expressPaymentMethod === 'googlePay' ) {
+ return (
+
+ );
+ }
+
+ if ( expressPaymentMethod === 'applePay' ) {
+ return (
+
+ );
+ }
+
+ return null;
+};
+
+export default ExpressCheckoutButtonPreview;
diff --git a/client/express-checkout/blocks/components/express-checkout-component.js b/client/express-checkout/blocks/components/express-checkout-component.js
index bccfee2eb93..02d99524acd 100644
--- a/client/express-checkout/blocks/components/express-checkout-component.js
+++ b/client/express-checkout/blocks/components/express-checkout-component.js
@@ -11,6 +11,9 @@ import {
} from '../../event-handlers';
import { useExpressCheckout } from '../hooks/use-express-checkout';
import { PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT } from 'wcpay/checkout/constants';
+import ExpressCheckoutButtonPreview, {
+ SUPPORTED_PREVIEW_PAYMENT_METHODS,
+} from './express-checkout-button-preview';
const getPaymentMethodsOverride = ( enabledPaymentMethod ) => {
const allDisabled = {
@@ -131,16 +134,28 @@ const ExpressCheckoutComponent = ( {
};
};
+ const checkoutElementOptions = {
+ ...withBlockOverride(),
+ ...adjustButtonHeights( withBlockOverride(), expressPaymentMethod ),
+ ...getPaymentMethodsOverride( expressPaymentMethod ),
+ };
+
+ if (
+ isPreview &&
+ SUPPORTED_PREVIEW_PAYMENT_METHODS.includes( expressPaymentMethod )
+ ) {
+ return (
+
+ );
+ }
+
return (
{
+ const googlePlayContainerRef = useRef( null );
+ const hasStartedLoadingGooglePlayButton = useRef( null );
+ const appearance = getExpressCheckoutButtonAppearance( buttonAttributes );
+ const borderRadius = appearance.variables.borderRadius;
+
+ useEffect( () => {
+ if (
+ googlePlayContainerRef.current &&
+ ! hasStartedLoadingGooglePlayButton.current
+ ) {
+ hasStartedLoadingGooglePlayButton.current = true;
+ ( async () => {
+ // The container may be inside an iframe, so we need to retrieve a reference to the document and window objects.
+ const targetDocument =
+ googlePlayContainerRef.current.ownerDocument;
+ const targetWindow = targetDocument.defaultView;
+ if ( ! targetWindow.google?.payments?.api?.PaymentsClient ) {
+ await new Promise( ( resolve ) => {
+ const script = document.createElement( 'script' );
+ script.src = 'https://pay.google.com/gp/p/js/pay.js';
+ script.onload = resolve;
+ targetDocument.head.appendChild( script );
+ } );
+ }
+
+ const googlePayClient = new targetWindow.google.payments.api.PaymentsClient(
+ {
+ environment: 'TEST',
+ }
+ );
+
+ const buttonColor = theme === 'black' ? 'black' : 'white'; // There is no 'outline' theme in Google Pay.
+
+ const button = googlePayClient.createButton( {
+ buttonType: options.buttonType.googlePay,
+ buttonColor,
+ buttonRadius: parseFloat( borderRadius ),
+ buttonSizeMode: 'fill',
+ onClick: () => {},
+ } );
+ googlePlayContainerRef.current.appendChild( button );
+ } )();
+ }
+ }, [ theme, borderRadius, options.buttonType.googlePay ] );
+
+ useEffect( () => {
+ googlePlayContainerRef.current
+ ?.querySelector( 'button' )
+ ?.style?.setProperty( 'border-radius', borderRadius );
+ }, [ borderRadius ] );
+
+ return (
+
+ );
+};
+
+const ApplePayButtonPreview = ( { options, buttonAttributes, theme } ) => {
+ const appearance = getExpressCheckoutButtonAppearance( buttonAttributes );
+ const borderRadius = appearance.variables.borderRadius;
+
+ const buttonStyle = {
+ height: `${ options.buttonHeight }px`,
+ borderRadius,
+ ApplePayButtonType: options.buttonType.applePay,
+ WebkitAppearance: '-apple-pay-button',
+ width: '100%',
+ };
+
+ if ( [ 'black', 'white', 'white-outline' ].includes( theme ) ) {
+ buttonStyle.ApplePayButtonStyle = theme;
+ } else {
+ buttonStyle.ApplePayButtonStyle = 'white';
+ }
+
+ return (
+
+
+
+ );
+};
+
+const ExpressCheckoutButtonPreview = ( {
+ expressPaymentMethod,
+ options,
+ buttonAttributes,
+} ) => {
+ const theme = options.buttonTheme[ expressPaymentMethod ];
+
+ if ( expressPaymentMethod === 'googlePay' ) {
+ return (
+
+ );
+ }
+
+ if ( expressPaymentMethod === 'applePay' ) {
+ return (
+
+ );
+ }
+
+ return null;
+};
+
+export default ExpressCheckoutButtonPreview;
diff --git a/client/tokenized-express-checkout/blocks/components/express-checkout-component.js b/client/tokenized-express-checkout/blocks/components/express-checkout-component.js
index 9975b56d406..b794b083e0b 100644
--- a/client/tokenized-express-checkout/blocks/components/express-checkout-component.js
+++ b/client/tokenized-express-checkout/blocks/components/express-checkout-component.js
@@ -11,6 +11,9 @@ import {
} from '../../event-handlers';
import { useExpressCheckout } from '../hooks/use-express-checkout';
import { PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT } from 'wcpay/checkout/constants';
+import ExpressCheckoutButtonPreview, {
+ SUPPORTED_PREVIEW_PAYMENT_METHODS,
+} from './express-checkout-button-preview';
const getPaymentMethodsOverride = ( enabledPaymentMethod ) => {
const allDisabled = {
@@ -131,16 +134,28 @@ const ExpressCheckoutComponent = ( {
};
};
+ const checkoutElementOptions = {
+ ...withBlockOverride(),
+ ...adjustButtonHeights( withBlockOverride(), expressPaymentMethod ),
+ ...getPaymentMethodsOverride( expressPaymentMethod ),
+ };
+
+ if (
+ isPreview &&
+ SUPPORTED_PREVIEW_PAYMENT_METHODS.includes( expressPaymentMethod )
+ ) {
+ return (
+
+ );
+ }
+
return (