Skip to content

Commit e8a48cb

Browse files
Alex FloriscaoprKristófer Rreykjalin
authored
Integrate express payments buttonAttributes API from the Checkout Block (#8888)
Co-authored-by: Thomas Roberts <[email protected]> Co-authored-by: Kristófer R <[email protected]> Co-authored-by: Kristófer Reykjalín <[email protected]>
1 parent 172ab2a commit e8a48cb

File tree

10 files changed

+138
-43
lines changed

10 files changed

+138
-43
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: add
3+
4+
Add compatibility with the buttonAttributes API from Woo Blocks

client/checkout/woopay/express-button/test/woopay-express-checkout-button.test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,27 @@ describe( 'WoopayExpressCheckoutButton', () => {
128128
).toBeInTheDocument();
129129
} );
130130

131+
test( 'respect buttonAttributes API when available ', () => {
132+
render(
133+
<WoopayExpressCheckoutButton
134+
isPreview={ false }
135+
buttonSettings={ buttonSettings }
136+
api={ api }
137+
isProductPage={ false }
138+
emailSelector="#email"
139+
buttonAttributes={ {
140+
height: '55',
141+
borderRadius: '20',
142+
} }
143+
/>
144+
);
145+
146+
const button = screen.queryByRole( 'button', { name: 'WooPay' } );
147+
expect( button.getAttribute( 'style' ) ).toBe(
148+
'height: 55px; border-radius: 20px;'
149+
);
150+
} );
151+
131152
test( 'does not prefetch session data by default', async () => {
132153
getConfig.mockImplementation( ( v ) => {
133154
switch ( v ) {

client/checkout/woopay/express-button/woopay-express-checkout-button.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const WoopayExpressCheckoutButton = ( {
4040
api,
4141
isProductPage = false,
4242
emailSelector = '#email',
43+
buttonAttributes,
4344
} ) => {
4445
const buttonWidthTypes = {
4546
narrow: 'narrow',
@@ -48,10 +49,9 @@ export const WoopayExpressCheckoutButton = ( {
4849
const onClickCallbackRef = useRef( null );
4950
const buttonRef = useRef( null );
5051
const isLoadingRef = useRef( false );
51-
const {
52+
let {
53+
height: buttonHeight,
5254
type: buttonType,
53-
height,
54-
size,
5555
theme,
5656
context,
5757
radius: borderRadius,
@@ -60,6 +60,18 @@ export const WoopayExpressCheckoutButton = ( {
6060
const [ buttonWidthType, setButtonWidthType ] = useState(
6161
buttonWidthTypes.wide
6262
);
63+
const buttonSizeMap = new Map();
64+
buttonSizeMap.set( '40', 'small' );
65+
buttonSizeMap.set( '48', 'medium' );
66+
buttonSizeMap.set( '55', 'large' );
67+
68+
// If we are on the checkout block, we receive button attributes which overwrite the extension specific settings
69+
if ( typeof buttonAttributes !== 'undefined' ) {
70+
buttonHeight = buttonAttributes.height || buttonHeight;
71+
borderRadius = buttonAttributes.borderRadius || borderRadius;
72+
}
73+
74+
const buttonSize = buttonSizeMap.get( buttonHeight );
6375

6476
const buttonText =
6577
ButtonTypeTextMap[ buttonType || 'default' ] ??
@@ -353,18 +365,18 @@ export const WoopayExpressCheckoutButton = ( {
353365
return (
354366
<button
355367
ref={ buttonRef }
356-
key={ `${ buttonType }-${ theme }-${ size }` }
368+
key={ `${ buttonType }-${ theme }-${ buttonSize }` }
357369
aria-label={ buttonText }
358370
onClick={ ( e ) => onClickCallbackRef.current( e ) }
359371
className={ classNames( 'woopay-express-button', {
360372
'is-loading': isLoading,
361373
} ) }
362374
data-type={ buttonType }
363-
data-size={ size }
375+
data-size={ buttonSize }
364376
data-theme={ theme }
365377
data-width-type={ buttonWidthType }
366378
style={ {
367-
height: `${ height }px`,
379+
height: `${ buttonHeight }px`,
368380
borderRadius: `${ borderRadius }px`,
369381
} }
370382
disabled={ isLoading }

client/checkout/woopay/express-button/woopay-express-checkout-payment-method.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,24 @@ const api = new WCPayAPI(
2525
request
2626
);
2727

28-
const WooPayExpressCheckoutButtonContainer = () => {
29-
const onRefChange = useCallback( ( node ) => {
30-
if ( node ) {
31-
const root = ReactDOM.createRoot( node );
28+
const WooPayExpressCheckoutButtonContainer = ( { buttonAttributes } ) => {
29+
const onRefChange = useCallback(
30+
( node ) => {
31+
if ( node ) {
32+
const root = ReactDOM.createRoot( node );
3233

33-
root.render(
34-
<WoopayExpressCheckoutButton
35-
buttonSettings={ getConfig( 'woopayButton' ) }
36-
api={ api }
37-
emailSelector="#email"
38-
/>
39-
);
40-
}
41-
}, [] );
34+
root.render(
35+
<WoopayExpressCheckoutButton
36+
buttonSettings={ getConfig( 'woopayButton' ) }
37+
api={ api }
38+
emailSelector="#email"
39+
buttonAttributes={ buttonAttributes }
40+
/>
41+
);
42+
}
43+
},
44+
[ buttonAttributes ]
45+
);
4246

4347
return <span ref={ onRefChange } />;
4448
};

client/express-checkout/blocks/components/express-checkout-component.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const ExpressCheckoutComponent = ( {
7575
onClick,
7676
onClose,
7777
expressPaymentMethod = '',
78+
buttonAttributes,
7879
} ) => {
7980
const {
8081
buttonOptions,
@@ -116,10 +117,27 @@ const ExpressCheckoutComponent = ( {
116117
onReady( event );
117118
};
118119

120+
// The Cart & Checkout blocks provide unified styles across all buttons,
121+
// which should override the extension specific settings.
122+
const withBlockOverride = () => {
123+
const override = {};
124+
if ( typeof buttonAttributes !== 'undefined' ) {
125+
override.buttonHeight = Number( buttonAttributes.height );
126+
}
127+
return {
128+
...buttonOptions,
129+
...override,
130+
};
131+
};
132+
119133
return (
120134
<ExpressCheckoutElement
121135
options={ {
122-
...adjustButtonHeights( buttonOptions, expressPaymentMethod ),
136+
...withBlockOverride( buttonOptions ),
137+
...adjustButtonHeights(
138+
withBlockOverride( buttonOptions ),
139+
expressPaymentMethod
140+
),
123141
...getPaymentMethodsOverride( expressPaymentMethod ),
124142
} }
125143
onClick={ onButtonClick }

client/express-checkout/blocks/components/express-checkout-container.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { getExpressCheckoutButtonAppearance } from 'wcpay/express-checkout/utils
1212
import '../express-checkout-element.scss';
1313

1414
const ExpressCheckoutContainer = ( props ) => {
15-
const { api, billing } = props;
15+
const { api, billing, buttonAttributes } = props;
1616

1717
const stripePromise = useMemo( () => {
1818
return api.loadStripe( true );
@@ -23,7 +23,7 @@ const ExpressCheckoutContainer = ( props ) => {
2323
paymentMethodCreation: 'manual',
2424
amount: billing.cartTotal.value,
2525
currency: billing.currency.code.toLowerCase(),
26-
appearance: getExpressCheckoutButtonAppearance(),
26+
appearance: getExpressCheckoutButtonAppearance( buttonAttributes ),
2727
};
2828

2929
return (

client/express-checkout/utils/index.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,18 +169,31 @@ export const displayLoginConfirmation = (
169169
}
170170
};
171171

172+
type ButtonAttributesType =
173+
| { height: string; borderRadius: string }
174+
| undefined;
175+
172176
/**
173177
* Returns the appearance settings for the Express Checkout buttons.
174178
* Currently only configures border radius for the buttons.
175179
*/
176-
export const getExpressCheckoutButtonAppearance = () => {
180+
export const getExpressCheckoutButtonAppearance = (
181+
buttonAttributes: ButtonAttributesType
182+
) => {
183+
let borderRadius = getDefaultBorderRadius();
177184
const buttonSettings = getExpressCheckoutData( 'button' );
178185

186+
// Border radius from WooPayments settings
187+
borderRadius = buttonSettings?.radius ?? borderRadius;
188+
189+
// Border radius from Cart & Checkout blocks attributes
190+
if ( typeof buttonAttributes !== 'undefined' ) {
191+
borderRadius = Number( buttonAttributes?.borderRadius ) ?? borderRadius;
192+
}
193+
179194
return {
180195
variables: {
181-
borderRadius: `${
182-
buttonSettings?.radius || getDefaultBorderRadius()
183-
}px`,
196+
borderRadius: `${ borderRadius }px`,
184197
spacingUnit: '6px',
185198
},
186199
};

client/payment-request/blocks/payment-request-express.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { Elements, PaymentRequestButtonElement } from '@stripe/react-stripe-js';
99
* Internal dependencies
1010
*/
1111
import { useInitialization } from './use-initialization';
12-
import { getPaymentRequestData } from '../utils';
1312
import { recordUserEvent } from 'tracks';
1413
import { useEffect, useState } from 'react';
14+
import { getPaymentRequestData } from '../utils/utils';
1515

1616
/**
1717
* PaymentRequestExpressComponent
@@ -28,6 +28,7 @@ const PaymentRequestExpressComponent = ( {
2828
onClick,
2929
onClose,
3030
onPaymentRequestAvailable,
31+
buttonAttributes,
3132
} ) => {
3233
// TODO: Don't display custom button when result.requestType
3334
// is `apple_pay` or `google_pay`.
@@ -44,13 +45,18 @@ const PaymentRequestExpressComponent = ( {
4445
onClose,
4546
} );
4647

47-
const { type, theme, height } = getPaymentRequestData( 'button' );
48+
let { type, theme, height } = getPaymentRequestData( 'button' );
49+
50+
// If we are on the checkout block, we receive button attributes which overwrite the extension specific settings
51+
if ( typeof buttonAttributes !== 'undefined' ) {
52+
height = buttonAttributes.height || height;
53+
}
4854

4955
const paymentRequestButtonStyle = {
5056
paymentRequestButton: {
5157
type,
5258
theme,
53-
height: height + 'px',
59+
height: `${ height }px`,
5460
},
5561
};
5662

client/settings/express-checkout-settings/general-payment-request-button-settings.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -168,20 +168,31 @@ const GeneralPaymentRequestButtonSettings = ( { type } ) => {
168168
return (
169169
<CardBody>
170170
{ showWarning && (
171-
<InlineNotice
172-
status="warning"
173-
icon={ true }
174-
isDismissible={ false }
175-
>
176-
{ sprintf(
177-
/* translators: %s type of button to which the settings will be applied */
178-
__(
179-
'These settings will also apply to the %s on your store.',
180-
'woocommerce-payments'
181-
),
182-
otherButtons
183-
) }
184-
</InlineNotice>
171+
<>
172+
<InlineNotice
173+
status="warning"
174+
icon={ true }
175+
isDismissible={ false }
176+
>
177+
{ sprintf(
178+
/* translators: %s type of button to which the settings will be applied */
179+
__(
180+
'These settings will also apply to the %s on your store.',
181+
'woocommerce-payments'
182+
),
183+
otherButtons
184+
) }
185+
</InlineNotice>
186+
<InlineNotice
187+
status="warning"
188+
icon={ true }
189+
isDismissible={ false }
190+
>
191+
{ __(
192+
'Some appearance settings may be overridden in the express payment section of the Cart & Checkout blocks.'
193+
) }
194+
</InlineNotice>
195+
</>
185196
) }
186197
<h4>{ __( 'Call to action', 'woocommerce-payments' ) }</h4>
187198
<SelectControl

client/utils/express-checkout/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ export const getExpressCheckoutConfig = ( key ) => {
2323
};
2424

2525
export const getDefaultBorderRadius = () => {
26+
// If wcpaySettings isn't loaded on the page where this is called we can
27+
// safely return the default value of 4.
28+
if ( typeof wcpaySettings === 'undefined' ) {
29+
return 4;
30+
}
31+
2632
return parseInt(
2733
window?.wcpaySettings?.defaultExpressCheckoutBorderRadius || 4,
2834
10

0 commit comments

Comments
 (0)