Skip to content

Commit

Permalink
Move plans UI into a package (#42764)
Browse files Browse the repository at this point in the history
* Create `@automattic/plans-grid` package.
* Use the new package in Gutenboarding to display as modal and as a step.
* PlansGrid component get `header` as a prop.

Co-authored-by: Razvan Papadopol <razvan.papadopol@automattic.com>
  • Loading branch information
alshakero and Razvan Papadopol authored Jun 4, 2020
1 parent 828dc66 commit b9c508a
Show file tree
Hide file tree
Showing 29 changed files with 452 additions and 79 deletions.
2 changes: 1 addition & 1 deletion client/landing/gutenboarding/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { USER_STORE } from '../../stores/user';
import { SITE_STORE } from '../../stores/site';
import './style.scss';
import DomainPickerButton from '../domain-picker-button';
import PlansButton from '../plans/plans-button';
import PlansButton from '../plans-button';
import SignupForm from '../../components/signup-form';
import { useDomainSuggestions } from '../../hooks/use-domain-suggestions';
import { useShouldSiteBePublicOnSelectedPlan } from '../../hooks/use-selected-plan';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import classnames from 'classnames';
*/
import JetpackLogo from 'components/jetpack-logo'; // @TODO: extract to @automattic package
import PlansModal from '../plans-modal';
import { useSelectedPlan } from '../../../hooks/use-selected-plan';
import { useCurrentStep, Step } from '../../../path';
import { PLANS_STORE } from '../../../stores/plans';
import { useSelectedPlan } from '../../hooks/use-selected-plan';
import { useCurrentStep, Step } from '../../path';
import { PLANS_STORE } from '../../stores/plans';

/**
* Style dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@ import Modal from 'react-modal';
import { useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import PlansGrid from '@automattic/plans-grid';

/**
* Internal dependencies
*/
import { PLANS_STORE } from '../../../stores/plans';
import PlansGrid, { Props as PlansGridProps } from '../plans-grid';
import { useTrackModal } from '../../../hooks/use-track-modal';
import { useSelectedPlan } from '../../../hooks/use-selected-plan';
import { PLANS_STORE } from '../../stores/plans';
import { useTrackModal } from '../../hooks/use-track-modal';
import { useSelectedPlan } from '../../hooks/use-selected-plan';
import ActionButtons from '../action-buttons';
import { Title, SubTitle } from '../titles';

/**
* Style dependencies
*/
import './style.scss';

interface Props extends Partial< PlansGridProps > {
interface Props {
onClose: () => void;
}

Expand Down Expand Up @@ -51,25 +53,39 @@ const PlansGridModal: React.FunctionComponent< Props > = ( { onClose } ) => {
onClose();
};

return (
<Modal
isOpen
className="gutenboarding-page plans-modal"
overlayClassName="plans-modal-overlay"
bodyOpenClassName="has-plans-modal"
>
<PlansGrid
confirmButton={
const header = (
<>
<div>
<Title>{ __( 'Choose a plan' ) }</Title>
<SubTitle>
{ __(
'Pick a plan that’s right for you. Switch plans as your needs change. There’s no risk, you can cancel for a full refund within 30 days.'
) }
</SubTitle>
</div>
<ActionButtons
primaryButton={
<Button isPrimary onClick={ handleConfirm }>
{ __( 'Confirm' ) }
</Button>
}
cancelButton={
secondaryButton={
<Button isLink onClick={ onClose }>
{ __( 'Close' ) }
</Button>
}
/>
</>
);

return (
<Modal
isOpen
className="gutenboarding-page plans-modal"
overlayClassName="plans-modal-overlay"
bodyOpenClassName="has-plans-modal"
>
<PlansGrid header={ header } currentPlan={ plan } />
</Modal>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import '../../../mixins.scss';
@import '../../mixins.scss';

.plans-modal-overlay {
@include onboarding-modal-overlay;
Expand Down
28 changes: 22 additions & 6 deletions client/landing/gutenboarding/onboarding-block/plans/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import React, { useEffect, useRef, useState } from 'react';
import { useI18n } from '@automattic/react-i18n';
import { Button } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import PlansGrid from '@automattic/plans-grid';

/**
* Internal dependencies
*/
import PlansGrid from '../../components/plans/plans-grid';
import SignupForm from '../../components/signup-form';
import Link from '../../components/link';
import {
Expand All @@ -21,6 +21,8 @@ import { useFreeDomainSuggestion } from '../../hooks/use-free-domain-suggestion'
import { USER_STORE } from '../../stores/user';
import { STORE_KEY as ONBOARD_STORE } from '../../stores/onboard';
import { usePath, Step } from '../../path';
import ActionButtons from '../../components/action-buttons';
import { Title, SubTitle } from '../../components/titles';

export default function PlansStep() {
const { __ } = useI18n();
Expand Down Expand Up @@ -54,10 +56,18 @@ export default function PlansStep() {
createSite( username, freeDomainSuggestion, bearerToken, shouldSiteBePublic );
};

return (
<div className="gutenboarding-page plans">
<PlansGrid
confirmButton={
const header = (
<>
<div>
<Title>{ __( 'Choose a plan' ) }</Title>
<SubTitle>
{ __(
'Pick a plan that’s right for you. Switch plans as your needs change. There’s no risk, you can cancel for a full refund within 30 days.'
) }
</SubTitle>
</div>
<ActionButtons
primaryButton={
<Button
isPrimary
onClick={ () => {
Expand All @@ -67,12 +77,18 @@ export default function PlansStep() {
{ __( 'Continue' ) }
</Button>
}
cancelButton={
secondaryButton={
<Link className="plans__back-link" isLink to={ makePath( Step.Style ) }>
{ __( 'Go back' ) }
</Link>
}
/>
</>
);

return (
<div className="gutenboarding-page plans">
<PlansGrid header={ header } currentPlan={ plan } />
{ showSignupDialog && <SignupForm onRequestClose={ () => setShowSignupDialog( false ) } /> }
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@automattic/composite-checkout": "^1.0.0",
"@automattic/data-stores": "^1.0.0-alpha.1",
"@automattic/domain-picker": "^1.0.0-alpha.0",
"@automattic/plans-grid": "^1.0.0-alpha.0",
"@automattic/format-currency": "^1.0.0-alpha.0",
"@automattic/lasagna": "^0.5.4",
"@automattic/load-script": "^1.0.0",
Expand Down Expand Up @@ -57,7 +58,6 @@
"@wordpress/notices": "^2.4.0",
"@wordpress/nux": "^3.16.0",
"@wordpress/plugins": "^2.16.0",
"@wordpress/primitives": "^1.5.0",
"@wordpress/redux-routine": "^3.9.0",
"@wordpress/rich-text": "^3.16.0",
"@wordpress/server-side-render": "^1.12.0",
Expand Down
12 changes: 6 additions & 6 deletions packages/data-stores/src/plans/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import reducer, { State } from './reducer';
import * as actions from './actions';
import * as selectors from './selectors';
import * as resolvers from './resolvers';
import { plansPaths } from './plans-data';

export type { State };
export type { Plan, PlanSlug } from './types';

// used to construct the route that accepts plan slugs like (/beginner, /business, etc..)
export { plansPaths } from './plans-data';

let isRegistered = false;

Expand All @@ -36,8 +41,3 @@ declare module '@wordpress/data' {
function dispatch( key: typeof STORE_KEY ): DispatchFromMap< typeof actions >;
function select( key: typeof STORE_KEY ): SelectFromMap< typeof selectors >;
}

export type { Plan, PlanSlug } from './types';

// used to construct the route that accepts plan slugs like (/beginner, /business, etc..)
export { plansPaths, State };
10 changes: 4 additions & 6 deletions packages/data-stores/src/plans/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import { planDetails, PLANS_LIST } from './plans-data';
import { DEFAULT_PAID_PLAN, PLAN_FREE, PLAN_ECOMMERCE } from './constants';
import type { PlanSlug } from './types';

function getPlan( slug?: PlanSlug ) {
if ( slug ) {
return PLANS_LIST[ slug ];
}
return null;
function getPlan( slug: PlanSlug ) {
return PLANS_LIST[ slug ];
}

export const getSelectedPlan = ( state: State ) => getPlan( state.selectedPlanSlug );
export const getSelectedPlan = ( state: State ) =>
state.selectedPlanSlug ? getPlan( state.selectedPlanSlug ) : null;

export const getDefaultPlan = ( _: State, hasPaidDomain: boolean, hasPaidDesign: boolean ) =>
hasPaidDomain || hasPaidDesign ? getPlan( DEFAULT_PAID_PLAN ) : getPlan( PLAN_FREE );
Expand Down
5 changes: 5 additions & 0 deletions packages/plans-grid/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
rules: {
'import/no-extraneous-dependencies': [ 'error', { packageDir: __dirname } ],
},
};
54 changes: 54 additions & 0 deletions packages/plans-grid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"name": "@automattic/plans-grid",
"version": "1.0.0-alpha.0",
"description": "WordPress.com Plans Grid UI component",
"homepage": "https://github.com/Automattic/wp-calypso",
"license": "GPL-2.0-or-later",
"author": "Automattic Inc.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"sideEffects": [
"*.css",
"*.scss"
],
"repository": {
"type": "git",
"url": "git+https://github.com/Automattic/wp-calypso.git",
"directory": "packages/plans-grid"
},
"publishConfig": {
"access": "public"
},
"bugs": {
"url": "https://github.com/Automattic/wp-calypso/issues"
},
"types": "dist/types",
"scripts": {
"clean": "check-npm-client && npx rimraf dist ../../.tsc-cache/packages__plans-grid*",
"prepare": "check-npm-client && tsc --project ./tsconfig.json && tsc --project ./tsconfig-cjs.json && copy-assets",
"prepublish": "check-npm-client && yarn run clean",
"watch": "check-npm-client && tsc --project ./tsconfig.json --watch"
},
"dependencies": {
"@automattic/data-stores": "^1.0.0-alpha.1",
"@automattic/react-i18n": "^1.0.0-alpha.0",
"@wordpress/components": "^9.6.0",
"@wordpress/icons": "^2.0.0",
"@wordpress/primitives": "^1.5.0",
"classnames": "^2.2.6",
"lodash": "^4.17.15",
"tslib": "^1.10.0",
"use-debounce": "^3.1.0",
"uuid": "^7.0.2"
},
"devDependencies": {
"@wordpress/base-styles": "^1.8.0"
},
"peerDependencies": {
"@wordpress/data": "^4.18.0",
"@wordpress/element": "^2.14.0",
"@wordpress/i18n": "^3.10.0",
"react": "^16.8"
},
"private": true
}
25 changes: 25 additions & 0 deletions packages/plans-grid/src/badge/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* External dependencies
*/
import * as React from 'react';
import classNames from 'classnames';

/**
* Style dependencies
*/
import './style.scss';

// @TODO: move to '@automattic/components' and reuse in Gutenboarding

interface Props {
children: React.ReactElement[];
className?: string;
}

const Badge: React.FunctionComponent< Props > = ( { children, className, ...props } ) => (
<span { ...props } className={ classNames( 'badge', className ) }>
{ children }
</span>
);

export default Badge;
12 changes: 12 additions & 0 deletions packages/plans-grid/src/badge/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.badge {
display: inline-block;
background: var( --studio-blue-40 );
border-radius: 2px;
padding: 4px 8px;
color: var( --studio-white );
margin-left: 8px;

> * {
vertical-align: middle;
}
}
6 changes: 6 additions & 0 deletions packages/plans-grid/src/base-styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@import '~@wordpress/base-styles/z-index';
@import '~@wordpress/base-styles/colors';
@import '~@wordpress/base-styles/variables';
@import '~@wordpress/base-styles/breakpoints';
@import '~@wordpress/base-styles/mixins';
@import '~@wordpress/base-styles/animations';
File renamed without changes.
4 changes: 4 additions & 0 deletions packages/plans-grid/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* Internal dependencies
*/
export { default } from './plans-grid';
Loading

0 comments on commit b9c508a

Please sign in to comment.