Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update: payment method test mode label behavior #9647

Merged
merged 13 commits into from
Nov 7, 2024
4 changes: 4 additions & 0 deletions changelog/update-payment-method-test-mode-label
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: update

update: payment method "test mode" label at checkout to be displayed only when payment method is selected
5 changes: 4 additions & 1 deletion client/checkout/blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ Object.entries( enabledPaymentMethodsConfig )
label: (
<PaymentMethodLabel
api={ api }
upeConfig={ upeConfig }
title={ upeConfig.title }
countries={ upeConfig.countries }
iconLight={ upeConfig.icon }
iconDark={ upeConfig.darkIcon }
Comment on lines +113 to +116
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just like to be explicit 🤷

upeName={ upeName }
upeAppearanceTheme={ upeAppearanceTheme }
/>
Expand Down
109 changes: 71 additions & 38 deletions client/checkout/blocks/payment-method-label.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,50 @@ import './style.scss';
import { useEffect, useState } from '@wordpress/element';
import { getAppearance } from 'wcpay/checkout/upe-styles';

export default ( { api, upeConfig, upeName, upeAppearanceTheme } ) => {
const bnplMethods = [ 'affirm', 'afterpay_clearpay', 'klarna' ];
const PaymentMethodMessageWrapper = ( {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be on its own file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't think so, because it's not going to be used anywhere else - I just extracted it from the previous implementation because I thought it would make things slightly easier to scroll through, since there are a lot of if conditions to check for. 🤷

upeName,
countries,
currentCountry,
amount,
appearance,
children,
} ) => {
if ( ! bnplMethods.includes( upeName ) ) {
return null;
}

if ( amount <= 0 ) {
return null;
}

if ( ! currentCountry ) {
return null;
}

if ( ! appearance ) {
return null;
}

if ( countries.length !== 0 && ! countries.includes( currentCountry ) ) {
return null;
}

return (
<div className="payment-method-label__pmme-container">{ children }</div>
);
};

export default ( {
api,
title,
countries,
iconLight,
iconDark,
upeName,
upeAppearanceTheme,
} ) => {
const cartData = wp.data.select( 'wc/store/cart' ).getCartData();
const bnplMethods = [ 'affirm', 'afterpay_clearpay', 'klarna' ];
const isTestMode = getUPEConfig( 'testMode' );
const [ appearance, setAppearance ] = useState(
getUPEConfig( 'wcBlocksUPEAppearance' )
Expand All @@ -35,8 +76,6 @@ export default ( { api, upeConfig, upeName, upeAppearanceTheme } ) => {
window.wcBlocksCheckoutData?.storeCountry ||
'US';

const isCreditCard = upeName === 'card';

useEffect( () => {
async function generateUPEAppearance() {
// Generate UPE input styles.
Expand All @@ -56,50 +95,44 @@ export default ( { api, upeConfig, upeName, upeAppearanceTheme } ) => {
return (
<>
<div className="payment-method-label">
<span className="payment-method-label__label">
{ upeConfig.title }
</span>
{ isCreditCard && isTestMode && (
<span className="payment-method-label__label">{ title }</span>
{ isTestMode && (
<span className="test-mode badge">
{ __( 'Test Mode', 'woocommerce-payments' ) }
</span>
) }
<img
className="payment-methods--logos"
src={
upeAppearanceTheme === 'night'
? upeConfig.darkIcon
: upeConfig.icon
upeAppearanceTheme === 'night' ? iconDark : iconLight
}
alt={ upeConfig.title }
alt={ title }
/>
</div>
{ bnplMethods.includes( upeName ) &&
( upeConfig.countries.length === 0 ||
upeConfig.countries.includes( currentCountry ) ) &&
amount > 0 &&
currentCountry &&
appearance && (
<div className="bnpl-message">
<Elements
stripe={ api.getStripeForUPE( upeName ) }
options={ {
appearance: appearance,
} }
>
<PaymentMethodMessagingElement
options={ {
amount: amount || 0,
currency:
cartData.totals.currency_code || 'USD',
paymentMethodTypes: [ upeName ],
countryCode: currentCountry,
displayType: 'promotional_text',
} }
/>
</Elements>
</div>
) }
<PaymentMethodMessageWrapper
upeName={ upeName }
countries={ countries }
amount={ amount }
currentCountry={ currentCountry }
appearance={ appearance }
>
<Elements
stripe={ api.getStripeForUPE( upeName ) }
options={ {
appearance: appearance,
} }
>
<PaymentMethodMessagingElement
options={ {
amount: amount || 0,
currency: cartData.totals.currency_code || 'USD',
paymentMethodTypes: [ upeName ],
countryCode: currentCountry,
displayType: 'promotional_text',
} }
/>
</Elements>
</PaymentMethodMessageWrapper>
</>
);
};
32 changes: 22 additions & 10 deletions client/checkout/blocks/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ button.wcpay-stripelink-modal-trigger:hover {
}

.wc-block-checkout__payment-method {
input:checked ~ div {
.wc-block-components-radio-control__label {
> .payment-method-label {
.test-mode.badge {
// hiding the badge when the payment method is not selected
display: inline-block;
}

&__pmme-container {
display: none;
}
}
}
}

.wc-block-components-radio-control__label {
width: 100%;
display: block !important;
Expand Down Expand Up @@ -77,6 +92,7 @@ button.wcpay-stripelink-modal-trigger:hover {
color: #4d3716;
justify-self: start;
width: max-content;
display: none;
}

@include breakpoint( '<480px' ) {
Expand All @@ -88,13 +104,14 @@ button.wcpay-stripelink-modal-trigger:hover {
justify-self: end;
}
}
}

.bnpl-message {
width: 100%;
&__pmme-container {
width: 100%;
pointer-events: none;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to ensure that clicking on the Payment Method Messaging Element expands the payment method


@include breakpoint( '<480px' ) {
margin-top: 8px;
@include breakpoint( '<480px' ) {
margin-top: 8px;
}
}
}
}
Expand All @@ -112,11 +129,6 @@ button.wcpay-stripelink-modal-trigger:hover {
}

#payment-method {
label.wc-block-components-radio-control__option-checked {
.StripeElement {
display: none;
}
}
/* stylelint-disable-next-line selector-id-pattern */
#radio-control-wc-payment-method-options-woocommerce_payments_affirm__label
img {
Expand Down
119 changes: 44 additions & 75 deletions client/checkout/classic/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,48 @@

&.wc_payment_methods,
&.woocommerce-PaymentMethods {
li.payment_method_woocommerce_payments {
display: grid;
grid-template-columns: 0fr 0fr 1fr;
grid-template-rows: max-content;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally used grid on the li element to prevent layout issues with themes that don't hide the input[type=radio] element and replace it with a custom ::before icon in the label.

If you switch to a theme like twenty-twentyfour you'll see that the layout is broken due to this.

image

This is how it looks like in develop.
image

li[class*='payment_method_woocommerce_payments'] {
> input[name='payment_method'] {
align-self: center;

&:checked ~ label {
.label-title-container {
gap: 8px; /* 8px gap between .payment-method-title and .test-mode.badge */
}

.test-mode.badge {
// hiding the badge when the payment method is not selected
display: inline-block;
}

.stripe-pmme-container {
display: none;
}
}
}

> label {
grid-column: 3;
display: grid;
grid-template-columns: 0fr auto;
grid-template-rows: max-content;
grid-gap: 0;
margin-bottom: 0;

> .label-title-container {
grid-area: 1 / 2 / 2 / 3;
grid-template-columns: 16px 1fr auto;
grid-template-rows: auto auto;
gap: 0 16px;
align-items: center;

.label-title-container {
display: inline-flex;
align-items: center; /* Centers the elements vertically */
flex-wrap: wrap; /* Allows elements to go onto new lines if necessary */
margin-right: 8px; /* Space between label-title-container and img */
grid-column: 2 / 3;
gap: 8px;
}

.payment-method-title {
margin-right: 8px;
white-space: normal; /* Allows wrapping if text is too long */
}

.test-mode.badge {
display: inline-block;
display: none;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not displaying it by default - it'll be displayed only when the method is selected.

background-color: #fff2d7;
border-radius: 4px;
padding: 4px 6px;
Expand All @@ -75,73 +91,26 @@
line-height: 16px;
color: #4d3716;
vertical-align: middle;
white-space: nowrap; /* Prevents the badge text from wrapping */
}

img {
float: none;
grid-area: 1 / 4 / 2 / 5;
align-self: baseline;
grid-column: 3 / 4;
align-self: start;
justify-self: end;
margin-left: 1em;
}
}
> div.payment_box {
grid-area: 2 / 1 / 3 / 4;
}
}
}
}

li.wc_payment_method:has( .input-radio:not( :checked )
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved above - the different structure shouldn't be needed anymore.

+ label
.stripe-pmme-container ) {
display: grid;
grid-template-columns: min-content 1fr;
grid-template-rows: auto auto;
align-items: baseline;

.input-radio {
grid-row: 1;
grid-column: 1;
}

label {
grid-column: 2;
grid-row: 1;
}

img {
grid-row: 1 / span 2;
align-self: center;
}
.stripe-pmme-container {
&:empty {
display: none; /* hides container if empty, without affecting alignment */
}

.stripe-pmme-container {
width: 100%;
grid-column: 1;
grid-row-start: 2;
pointer-events: none;
}

.payment_box {
flex: 0 0 100%;
grid-row: 2;
grid-column: 1 / span 2;
}
}

li.wc_payment_method:has( .input-radio:checked
+ label
.stripe-pmme-container ) {
display: block;

.input-radio:checked {
+ label {
.stripe-pmme-container {
display: none;
}

img {
grid-column: 2;
pointer-events: none;
display: block;
grid-column: 1 / -1;
width: 100%;
margin-top: 8px; /* Space above it */
}
}
}
}
Expand Down
7 changes: 3 additions & 4 deletions includes/class-wc-payment-gateway-wcpay.php
Original file line number Diff line number Diff line change
Expand Up @@ -581,16 +581,15 @@ public function get_title() {
$title = parent::get_title();

if (
Payment_Method::CARD === $this->stripe_id &&
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Test mode" badge is now displayed on all methods, when test mode is enabled. It'll be displayed by CSS only when the payment method is selected.

( is_checkout() || is_add_payment_method_page() ) &&
! isset( $_GET['change_payment_method'] ) // phpcs:ignore WordPress.Security.NonceVerification
) {
$test_mode_badge = '';
if ( WC_Payments::mode()->is_test() ) {
$test_mode_badge = '<span class="test-mode badge">' . __( 'Test Mode', 'woocommerce-payments' ) . '</span>';
} else {
$test_mode_badge = '';
}
return '<div class="label-title-container"><span class="payment-method-title">&nbsp;' . $title . '</span>' . $test_mode_badge . '</div>';

return '<div class="label-title-container"><span class="payment-method-title">' . $title . '</span>' . $test_mode_badge . '</div>';
}

return $title;
Expand Down
2 changes: 1 addition & 1 deletion includes/class-wc-payments-blocks-payment-method.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function get_payment_method_script_handles() {
'wc-blocks-checkout-style',
plugins_url( 'dist/blocks-checkout.css', WCPAY_PLUGIN_FILE ),
[],
'1.0',
WC_Payments::get_file_version( 'dist/checkout.css' ),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting the version from the build file, so that it changes at each release and we can effectively cache bust it - otherwise we incur the risk of providing an older build (because it could be cached by the customer's browser or the merchant's CDN)

'all'
);
}
Expand Down
Loading
Loading