Skip to content

Commit c2a58e8

Browse files
authored
Add payments methods a/b test (#36705)
1 parent c5855f0 commit c2a58e8

File tree

6 files changed

+219
-28
lines changed

6 files changed

+219
-28
lines changed

client/blocks/subscription-length-picker/style.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
flex-basis: calc( 100% );
1919

2020
&:not( :first-child ) {
21-
margin-top: 20px;
21+
margin-top: 8px;
2222
}
2323

2424
@include breakpoint( '>960px' ) {

client/components/section-nav/item.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class NavItem extends PureComponent {
2525
selected: PropTypes.bool,
2626
tabIndex: PropTypes.number,
2727
onClick: PropTypes.func,
28+
onKeyPress: PropTypes.func,
2829
isExternalLink: PropTypes.bool,
2930
disabled: PropTypes.bool,
3031
count: PropTypes.oneOfType( [ PropTypes.number, PropTypes.bool ] ),
@@ -74,6 +75,7 @@ class NavItem extends PureComponent {
7475
disabled={ this.props.disabled }
7576
role="menuitem"
7677
rel={ this.props.isExternalLink ? 'external' : null }
78+
onKeyPress={ this.props.onKeyPress }
7779
>
7880
<span className={ 'section-nav-' + itemClassPrefix + '__text' }>
7981
{ this.props.children }

client/lib/abtest/active-tests.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,14 @@ export default {
124124
},
125125
defaultVariation: 'default',
126126
},
127+
checkoutPaymentTypes: {
128+
datestamp: '20191028',
129+
variations: {
130+
tabs: 50,
131+
radios: 50,
132+
},
133+
defaultVariation: 'tabs',
134+
allowExistingUsers: true,
135+
localeTargets: 'any',
136+
},
127137
};

client/my-sites/checkout/checkout/index.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,6 @@ export class Checkout extends React.Component {
793793
shouldShowTax={ shouldShowTax( this.props.cart ) }
794794
key="picker"
795795
/>
796-
<hr className="checkout__subscription-length-picker-separator" key="separator" />
797796
</React.Fragment>
798797
);
799798
}

client/my-sites/checkout/checkout/payment-box.jsx

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ import {
2626
WEB_PAYMENT_BASIC_CARD_METHOD,
2727
WEB_PAYMENT_APPLE_PAY_METHOD,
2828
} from 'lib/web-payment';
29+
import { abtest } from 'lib/abtest';
2930

3031
export class PaymentBox extends PureComponent {
3132
constructor() {
3233
super();
33-
this.handlePaymentMethodChange = this.handlePaymentMethodChange.bind( this );
3434
}
3535

3636
componentDidUpdate() {
@@ -44,14 +44,14 @@ export class PaymentBox extends PureComponent {
4444
}
4545
}
4646

47-
handlePaymentMethodChange( paymentMethod ) {
47+
handlePaymentMethodChange = paymentMethod => {
4848
const onSelectPaymentMethod = this.props.onSelectPaymentMethod;
4949
return function() {
5050
analytics.ga.recordEvent( 'Upgrades', 'Switch Payment Method' );
5151
analytics.tracks.recordEvent( 'calypso_checkout_switch_to_' + snakeCase( paymentMethod ) );
5252
onSelectPaymentMethod( paymentMethod );
5353
};
54-
}
54+
};
5555

5656
getPaymentProviderLabel( method ) {
5757
let labelLogo = (
@@ -124,6 +124,7 @@ export class PaymentBox extends PureComponent {
124124
href=""
125125
onClick={ this.handlePaymentMethodChange( method ) }
126126
selected={ this.props.currentPaymentMethod === method }
127+
onKeyPress={ event => this.choosePaymentMethodWithKeyboard( event, method ) }
127128
>
128129
{ this.getPaymentProviderLabel( method ) }
129130
</NavItem>
@@ -139,8 +140,45 @@ export class PaymentBox extends PureComponent {
139140
} );
140141
}
141142

143+
renderPaymentMethod = ( paymentMethods, isPaymentMethodTest, titleText ) => {
144+
if ( isPaymentMethodTest ) {
145+
return (
146+
<div className="payment-box__pm-test-wrapper">
147+
<h2 className="payment-box__pm-title">
148+
{ this.props.translate( 'Choose a payment method' ) }
149+
</h2>
150+
<ul className="payment-box__pm-wrapper">{ paymentMethods }</ul>
151+
</div>
152+
);
153+
}
154+
155+
if ( paymentMethods ) {
156+
return (
157+
<SectionNav selectedText={ titleText }>
158+
<NavTabs>{ paymentMethods }</NavTabs>
159+
</SectionNav>
160+
);
161+
}
162+
163+
return null;
164+
};
165+
166+
choosePaymentMethodWithKeyboard = ( event, method ) => {
167+
const code = event.keyCode || event.which;
168+
if ( code === 13 ) {
169+
//13 is the enter keycode
170+
this.props.onSelectPaymentMethod( method );
171+
}
172+
};
173+
142174
render() {
143-
const cardClass = classNames( 'payment-box', this.props.classSet ),
175+
const paymentMethods = this.getPaymentMethods();
176+
const isPaymentMethodTest = paymentMethods && abtest( 'checkoutPaymentTypes' ) === 'radios';
177+
const cardClass = classNames(
178+
'payment-box',
179+
this.props.classSet,
180+
isPaymentMethodTest && 'payment-box--payment-methods-test'
181+
),
144182
contentClass = classNames( 'payment-box__content', this.props.contentClassSet );
145183

146184
const titleText = this.props.currentPaymentMethod
@@ -151,20 +189,20 @@ export class PaymentBox extends PureComponent {
151189
} )
152190
: this.props.translate( 'Loading…' );
153191

154-
const paymentMethods = this.getPaymentMethods();
155-
156192
return (
157193
<div className="checkout__payment-box-container" key={ this.props.currentPage }>
158194
{ this.props.title ? <SectionHeader label={ this.props.title } /> : null }
159195

160-
{ paymentMethods && (
161-
<SectionNav selectedText={ titleText }>
162-
<NavTabs>{ paymentMethods }</NavTabs>
163-
</SectionNav>
164-
) }
196+
{ this.renderPaymentMethod( paymentMethods, isPaymentMethodTest, titleText ) }
165197

166198
<Card className={ cardClass }>
167199
<div className="checkout__box-padding">
200+
{ isPaymentMethodTest && (
201+
<h2 className="checkout__payment-information-title">
202+
{ this.props.translate( 'Enter your payment information' ) }
203+
</h2>
204+
) }
205+
168206
<div className={ contentClass }>{ this.props.children }</div>
169207
</div>
170208
</Card>

client/my-sites/checkout/checkout/style.scss

Lines changed: 157 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
@import 'jetpack-connect/colors.scss';
22

3+
@mixin section-border ( $position ) {
4+
&::before {
5+
display: block;
6+
content: '';
7+
position: absolute;
8+
#{ $position }: 0;
9+
left: -8px;
10+
width: calc( 100% + 16px );
11+
height: 1px;
12+
box-sizing: border-box;
13+
background: var( --color-border-subtle );
14+
15+
@include breakpoint( '>660px' ) {
16+
width: calc( 100% + 60px );
17+
left: -30px;
18+
}
19+
}
20+
}
21+
322
.checkout {
423
position: relative;
524

@@ -306,7 +325,7 @@
306325
}
307326

308327
.checkout__payment-box-section.is-selected.no-stored-cards {
309-
border-left: 1px solid var( --color-neutral-0 );
328+
border: 1px solid var( --color-neutral-5 );
310329
}
311330

312331
.checkout__payment-box-section.is-selected:not( .no-stored-cards ) .checkout__new-card-fields {
@@ -352,6 +371,10 @@
352371
}
353372
}
354373

374+
.checkout__payment-box-section {
375+
border: 1px solid var( --color-neutral-5 );
376+
}
377+
355378
.checkout__summary-toggle {
356379
cursor: pointer;
357380
display: block;
@@ -368,24 +391,29 @@
368391
// -----------------------------------
369392

370393
.subscription-length-picker {
371-
margin-top: 15px;
394+
position: relative;
395+
padding-bottom: 10px;
396+
margin: 15px 0;
397+
398+
@include breakpoint( '>660px' ) {
399+
padding-bottom: 30px;
400+
margin-bottom: 20px;
401+
}
402+
403+
@include section-border( bottom );
372404
}
373405

374-
&__subscription-length-picker-separator {
375-
display: none;
406+
.subscription-length-picker__header {
407+
margin-bottom: 8px;
408+
padding-top: 10px;
376409
position: relative;
377-
// Parent overflow is hidden, so 80px here is an arbitrary number
378-
// to make sure this element will cover entire width of the parent.
379-
// If it's wider, it's okay too.
380-
width: calc( 100% + 80px * 2 );
381-
left: -80px;
382-
margin-top: 1.7em;
383-
margin-bottom: 1.7em;
384-
background: var( --color-neutral-0 );
385-
}
386410

387-
.subscription-length-picker + &__subscription-length-picker-separator {
388-
display: block;
411+
@include breakpoint( '>660px' ) {
412+
margin-top: 30px;
413+
padding-top: 20px;
414+
}
415+
416+
@include section-border( top );
389417
}
390418

391419
// PayPal Payment Box
@@ -859,6 +887,7 @@
859887
.checkout__alternative-payment-methods {
860888
float: right;
861889
}
890+
862891
.checkout__payment-box-container {
863892
.select-dropdown__option {
864893
&:first-child {
@@ -1158,3 +1187,116 @@
11581187
height: 40px;
11591188
}
11601189
}
1190+
1191+
/* Payment Methods Test
1192+
======================================= */
1193+
.payment-box__pm-test-wrapper {
1194+
background: var( --color-surface );
1195+
padding: 10px 8px 0;
1196+
1197+
@include breakpoint( '>660px' ) {
1198+
padding: 25px 30px 0;
1199+
}
1200+
}
1201+
1202+
.payment-box__pm-title {
1203+
font-size: 16px;
1204+
margin-bottom: 8px;
1205+
}
1206+
1207+
.payment-box__pm-wrapper {
1208+
margin: 0;
1209+
padding: 0;
1210+
1211+
.section-nav-tab {
1212+
list-style: none;
1213+
border: 0;
1214+
margin: 8px 0 0;
1215+
position: relative;
1216+
1217+
&:first-child {
1218+
margin-top: 0 !important;
1219+
}
1220+
1221+
&::after {
1222+
display: block;
1223+
content: '';
1224+
position: absolute;
1225+
top: 50%;
1226+
transform: translateY( -50% );
1227+
left: 15px;
1228+
width: 21px;
1229+
height: 21px;
1230+
border: 1px solid var( --color-neutral-10 );
1231+
border-radius: 50%;
1232+
box-sizing: border-box;
1233+
}
1234+
1235+
&::before {
1236+
display: block;
1237+
content: '';
1238+
position: absolute;
1239+
top: 50%;
1240+
transform: translateY( -50% ) scale( 0.8 );
1241+
left: 19px;
1242+
width: 13px;
1243+
height: 13px;
1244+
background: var( --color-surface );
1245+
border-radius: 50%;
1246+
box-sizing: border-box;
1247+
transition: transform 0.3s ease;
1248+
}
1249+
1250+
&.is-selected::before {
1251+
transform: translateY( -50% ) scale( 1 );
1252+
background: var( --color-primary );
1253+
}
1254+
1255+
&.is-selected .section-nav-tab__link::before {
1256+
border: 3px solid var( --color-primary );
1257+
}
1258+
}
1259+
1260+
.section-nav-tab__link {
1261+
color: var( --color-text );
1262+
font-weight: 400;
1263+
position: relative;
1264+
padding: 16px 16px 16px 47px;
1265+
background: transparent !important;
1266+
1267+
&::before {
1268+
display: block;
1269+
content: '';
1270+
position: absolute;
1271+
top: 0;
1272+
left: 0;
1273+
width: 100%;
1274+
height: 100%;
1275+
box-sizing: border-box;
1276+
border: 1px solid var( --color-border );
1277+
border-radius: 3px;
1278+
}
1279+
1280+
&:hover::before {
1281+
border: 3px solid var( --color-primary );
1282+
}
1283+
}
1284+
}
1285+
1286+
.payment-box--payment-methods-test {
1287+
box-shadow: none;
1288+
}
1289+
1290+
.checkout__payment-information-title {
1291+
font-size: 16px;
1292+
margin-bottom: 8px;
1293+
padding-top: 10px;
1294+
position: relative;
1295+
1296+
@include breakpoint( '>660px' ) {
1297+
margin: 20px 0 8px;
1298+
padding-top: 20px;
1299+
}
1300+
1301+
@include section-border( top );
1302+
}

0 commit comments

Comments
 (0)