Skip to content

Commit

Permalink
Reduce Amount of Steps in the MOX (#8426)
Browse files Browse the repository at this point in the history
Co-authored-by: Oleksandr Aratovskyi <[email protected]>
Co-authored-by: oaratovskyi <[email protected]>
  • Loading branch information
3 people authored Mar 22, 2024
1 parent a5ecdf6 commit 61cce82
Show file tree
Hide file tree
Showing 33 changed files with 296 additions and 691 deletions.
4 changes: 4 additions & 0 deletions changelog/dev-8311-reduce-mox
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: update

Updates to reduce the amount of steps required during onboarding flow.
4 changes: 2 additions & 2 deletions client/components/custom-select-control/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
}

.components-custom-select-control__menu {
margin: $gap 1px;
border-color: $gray-700;
margin: -1px 1px;
border-color: $gray-300;
max-height: 300px;
}
}
7 changes: 0 additions & 7 deletions client/components/form/fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import CustomSelectControl, {
ControlProps as SelectControlProps,
Item as SelectItem,
} from '../custom-select-control';
import PhoneNumberControl, {
PhoneNumberControlProps,
} from '../phone-number-control';
import GroupedSelectControl, {
GroupedSelectControlProps,
ListItem as GroupedSelectItem,
Expand All @@ -28,7 +25,6 @@ interface CommonProps {
export type TextFieldProps = TextControl.Props & CommonProps;
export type SelectFieldProps< ItemType > = SelectControlProps< ItemType > &
CommonProps;
export type PhoneNumberFieldProps = PhoneNumberControlProps & CommonProps;
export type GroupedSelectFieldProps< ItemType > = GroupedSelectControlProps<
ItemType
> &
Expand Down Expand Up @@ -71,9 +67,6 @@ export const SelectField = < ItemType extends SelectItem >(
props: SelectFieldProps< ItemType >
): JSX.Element => makeField( CustomSelectControl, props );

export const PhoneNumberField: React.FC< PhoneNumberFieldProps > = ( props ) =>
makeField( PhoneNumberControl, props );

export const GroupedSelectField = < ItemType extends GroupedSelectItem >(
props: GroupedSelectControlProps< ItemType >
): JSX.Element => makeField( GroupedSelectControl, props );
18 changes: 1 addition & 17 deletions client/components/form/test/fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ import { render, screen } from '@testing-library/react';
/**
* Internal dependencies
*/
import {
TextField,
SelectField,
PhoneNumberField,
GroupedSelectField,
} from '../fields';
import { TextField, SelectField, GroupedSelectField } from '../fields';

describe( 'Form fields components', () => {
it( 'renders TextField component with provided props', () => {
Expand Down Expand Up @@ -43,17 +38,6 @@ describe( 'Form fields components', () => {
expect( screen.getByText( 'Test Label' ) ).toBeInTheDocument();
} );

it( 'renders PhoneNumberField component with provided props', () => {
render(
<PhoneNumberField
label="Test Label"
value="123"
onChange={ jest.fn() }
/>
);
expect( screen.getByText( 'Test Label' ) ).toBeInTheDocument();
} );

it( 'renders GroupedSelectField component with provided props', () => {
const options = [
{ key: 'option-1', name: 'Option 1', group: 'a' },
Expand Down
19 changes: 13 additions & 6 deletions client/components/grouped-select-control/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,24 @@
&.placeholder {
color: $gray-50;
}

@media screen and ( max-width: 782px ) {
font-size: 16px;
}
}

& &__search {
min-height: 36px;
width: 100%;
margin: 0;
border: 0;
padding: $gap-smaller $gap-small;
border-radius: 0;
border-bottom: 1px solid $gray-700;
border-bottom: 1px solid $gray-300;

&:focus {
box-shadow: none;
border-color: $gray-700;
border-color: $gray-300;
}
}

Expand All @@ -51,7 +56,7 @@
min-width: 100%;
background-color: #fff;
border-radius: 2px;
border: 1px solid $gray-700;
border: 1px solid $gray-300;
margin: $gap 1px;
z-index: 10000;
display: flex;
Expand Down Expand Up @@ -83,12 +88,14 @@
}

&.is-group {
text-transform: uppercase;
color: $gray-40;
font-weight: 600;
color: $gray-700;
}
}

&__list {
margin: -1px 1px;
}

& &__search,
&__list {
font-size: 13px;
Expand Down
11 changes: 10 additions & 1 deletion client/components/inline-notice/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Action } from 'wcpay/types/notices';
* Internal dependencies.
*/
import './styles.scss';
import ButtonVariant = Button.ButtonVariant;

interface InlineNoticeProps extends Notice.Props {
/**
Expand All @@ -24,13 +25,20 @@ interface InlineNoticeProps extends Notice.Props {
icon?: boolean | JSX.Element;

actions?: readonly Action[] | undefined;
/**
* Allows more control over the button variant.
* Accepted values are 'primary', 'secondary', 'tertiary', and 'link'.
*
* @default undefined
*/
buttonVariant?: ButtonVariant;
}

/**
* Renders a banner notice.
*/
function InlineNotice( props: InlineNoticeProps ): JSX.Element {
const { icon, actions, children, ...noticeProps } = props;
const { icon, actions, children, buttonVariant, ...noticeProps } = props;

// Add the default class name to the notice.
noticeProps.className = classNames(
Expand Down Expand Up @@ -77,6 +85,7 @@ function InlineNotice( props: InlineNoticeProps ): JSX.Element {
onClick={ action.onClick }
isBusy={ action.isBusy ?? false }
disabled={ action.disabled ?? false }
variant={ buttonVariant }
>
{ action.label }
</Button>
Expand Down
8 changes: 8 additions & 0 deletions client/components/inline-notice/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,12 @@
color: $wp-green-70;
}
}

// Special case for link variant button.
button.wcpay-inline-notice__action {
&.is-link {
text-decoration: none; // Remove underline.
box-shadow: none; // Remove box shadow.
}
}
}
6 changes: 6 additions & 0 deletions client/connect-account-page/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,12 @@
button {
@include wp-subtitle;
padding: $gap $gap-largest $gap $gap-large !important;
&:focus {
box-shadow: none !important;
}
&:hover {
background: #fff !important;
}
}
}
.components-notice {
Expand Down
10 changes: 1 addition & 9 deletions client/globals.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
/**
* Internal dependencies
*/
import type {
MccsDisplayTreeItem,
Country,
OnboardingFields,
} from 'onboarding/types';
import type { MccsDisplayTreeItem, Country } from 'onboarding/types';

declare global {
const wcpaySettings: {
Expand Down Expand Up @@ -102,10 +98,6 @@ declare global {
business_types: Country[];
mccs_display_tree: MccsDisplayTreeItem[];
};
onboardingFlowState?: {
current_step: string;
data: OnboardingFields;
};
storeCurrency: string;
isMultiCurrencyEnabled: string;
errorMessage: string;
Expand Down
6 changes: 1 addition & 5 deletions client/onboarding/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import { isNil, omitBy } from 'lodash';
/**
* Internal dependencies
*/
import { OnboardingFields, TempData } from './types';
import { OnboardingFields } from './types';

const useContextValue = ( initialState = {} as OnboardingFields ) => {
const [ data, setData ] = useState( initialState );
const [ errors, setErrors ] = useState( {} as OnboardingFields );
const [ touched, setTouched ] = useState( {} as OnboardingFields );
const [ temp, setTemp ] = useState( {} as TempData );

return {
data,
Expand All @@ -25,9 +24,6 @@ const useContextValue = ( initialState = {} as OnboardingFields ) => {
touched,
setTouched: ( value: Record< string, boolean > ) =>
setTouched( ( prev ) => ( { ...prev, ...value } ) ),
temp,
setTemp: ( value: Partial< TempData > ) =>
setTemp( ( prev ) => ( { ...prev, ...value } ) ),
};
};

Expand Down
46 changes: 9 additions & 37 deletions client/onboarding/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import { ListItem as GroupedSelectItem } from 'components/grouped-select-control
import {
GroupedSelectField,
GroupedSelectFieldProps,
PhoneNumberField,
PhoneNumberFieldProps,
SelectField,
SelectFieldProps,
TextField,
Expand Down Expand Up @@ -47,7 +45,11 @@ export const OnboardingForm: React.FC = ( { children } ) => {
} }
>
{ children }
<Button isPrimary type="submit" className="stepper__cta">
<Button
variant={ 'primary' }
type="submit"
className="stepper__cta"
>
{ strings.continue }
</Button>
</form>
Expand Down Expand Up @@ -90,38 +92,6 @@ export const OnboardingTextField: React.FC< OnboardingTextFieldProps > = (
);
};

interface OnboardingPhoneNumberFieldProps
extends Partial< PhoneNumberFieldProps > {
name: keyof OnboardingFields;
}

export const OnboardingPhoneNumberField: React.FC< OnboardingPhoneNumberFieldProps > = (
props
) => {
const { name } = props;
const { data, setData, temp, setTemp, touched } = useOnboardingContext();
const { validate, error } = useValidation( name );

return (
<PhoneNumberField
label={ strings.fields[ name ] }
value={ data[ name ] || '' }
country={ temp.phoneCountryCode || wcpaySettings.connect.country }
onChange={ ( value: string, phoneCountryCode: string ) => {
setTemp( { phoneCountryCode } );
setData( { [ name ]: value } );
if ( touched[ name ] ) validate( value );
} }
onBlur={ () => validate() }
error={ error() }
onKeyDown={ ( event: React.KeyboardEvent< HTMLInputElement > ) => {
if ( event.key === 'Enter' ) validate();
} }
{ ...props }
/>
);
};

interface OnboardingSelectFieldProps< ItemType >
extends Partial< Omit< SelectFieldProps< ItemType >, 'onChange' > > {
name: keyof OnboardingFields;
Expand All @@ -143,7 +113,8 @@ export const OnboardingSelectField = < ItemType extends SelectItem >( {
( item ) => item.key === data[ name ]
) }
placeholder={
( strings.placeholders as Record< string, string > )[ name ]
( strings.placeholders as Record< string, string > )[ name ] ??
strings.placeholders.generic
}
onChange={ ( { selectedItem } ) => {
if ( onChange ) {
Expand Down Expand Up @@ -183,7 +154,8 @@ export const OnboardingGroupedSelectField = <
( item ) => item.key === data[ name ]
) }
placeholder={
( strings.placeholders as Record< string, string > )[ name ]
( strings.placeholders as Record< string, string > )[ name ] ??
strings.placeholders.generic
}
onChange={ ( { selectedItem } ) => {
if ( onChange ) {
Expand Down
37 changes: 4 additions & 33 deletions client/onboarding/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,17 @@ import React, { useEffect } from 'react';
* Internal dependencies
*/
import Page from 'components/page';
import { OnboardingContextProvider, useOnboardingContext } from './context';
import { OnboardingContextProvider } from './context';
import { Stepper } from 'components/stepper';
import { OnboardingForm } from './form';
import Step from './step';
import PersonalDetails from './steps/personal-details';
import BusinessDetails from './steps/business-details';
import StoreDetails from './steps/store-details';
import LoadingStep from './steps/loading';
import { trackStarted } from './tracking';
import './style.scss';
import { persistFlowState } from './utils';

const OnboardingStepper = () => {
const { data } = useOnboardingContext();

const handleExit = () => {
if (
window.history.length > 1 &&
Expand All @@ -31,35 +27,10 @@ const OnboardingStepper = () => {
window.location.href = wcSettings.adminUrl;
};

const handleStepChange = ( step: string ) => {
window.scroll( 0, 0 );
persistFlowState( step, data );
};

const initialStep = () => {
// since mode step is not part of the stepper anymore, we need to overwrite it
// Remove it in a future version, once enough time has passed that people won't be likely to have mode or personal saved as this value.
const currentStep = wcpaySettings.onboardingFlowState?.current_step;
if (
currentStep &&
( currentStep === 'mode' || currentStep === 'personal' )
) {
return 'business';
}
return currentStep;
};
const handleStepChange = () => window.scroll( 0, 0 );

return (
<Stepper
initialStep={ initialStep() }
onStepChange={ handleStepChange }
onExit={ handleExit }
>
<Step name="personal">
<OnboardingForm>
<PersonalDetails />
</OnboardingForm>
</Step>
<Stepper onStepChange={ handleStepChange } onExit={ handleExit }>
<Step name="business">
<OnboardingForm>
<BusinessDetails />
Expand All @@ -75,7 +46,7 @@ const OnboardingStepper = () => {
);
};

const initialData = wcpaySettings.onboardingFlowState?.data ?? {
const initialData = {
business_name: wcSettings?.siteTitle,
url:
location.hostname === 'localhost'
Expand Down
Loading

0 comments on commit 61cce82

Please sign in to comment.