From 5516e348af1657adadd7cb917deb326628bc2cef Mon Sep 17 00:00:00 2001 From: Peter Zimon Date: Thu, 10 Jun 2021 17:21:10 +0200 Subject: [PATCH] Alpha version of multiple products - added Products grid component to signup page with static data - separate signup design between single vs. multiple products - alpha! --- ghost/portal/src/components/Frame.styles.js | 38 +- ghost/portal/src/components/PopupModal.js | 7 +- .../src/components/common/PlansSection.js | 2 +- .../src/components/common/ProductsSection.js | 337 ++++++++++++++++++ .../src/components/pages/AccountHomePage.js | 4 - .../portal/src/components/pages/SignupPage.js | 78 +++- ghost/portal/src/utils/fixtures.js | 6 +- 7 files changed, 449 insertions(+), 23 deletions(-) create mode 100644 ghost/portal/src/components/common/ProductsSection.js diff --git a/ghost/portal/src/components/Frame.styles.js b/ghost/portal/src/components/Frame.styles.js index 7a8076c182..b181675e89 100644 --- a/ghost/portal/src/components/Frame.styles.js +++ b/ghost/portal/src/components/Frame.styles.js @@ -12,6 +12,7 @@ import {AccountPlanPageStyles} from './pages/AccountPlanPage'; import {InputFieldStyles} from './common/InputField'; import {SignupPageStyles} from './pages/SignupPage'; import {PlanSectionStyles} from './common/PlansSection'; +import {ProductsSectionStyles} from './common/ProductsSection'; import {AvatarStyles} from './common/MemberGravatar'; import {MagicLinkStyles} from './pages/MagicLinkPage'; import {LinkPageStyles} from './pages/LinkPage'; @@ -233,6 +234,10 @@ const FrameStyles = ` height: 100%; } + .gh-portal-popup-wrapper.fullscreen { + padding: 0; + } + .gh-portal-popup-container { outline: none; position: relative; @@ -254,6 +259,16 @@ const FrameStyles = ` z-index: 9999; } + .gh-portal-popup-container.fullscreen { + align-items: center; + width: 100% !important; + height: 100% !important; + border-radius: 0px; + box-shadow: none !important; + overflow-y: scroll; + padding-bottom: 6vmin; + } + @keyframes popup { 0% { transform: scale(0.9) translateY(20px); @@ -303,6 +318,10 @@ const FrameStyles = ` margin: 0 6px 0 0; } + .gh-portal-popup-wrapper.fullscreen .gh-portal-powered { + z-index: 10000; + } + .gh-portal-container-wide { width: 440px; } @@ -348,7 +367,12 @@ const FrameStyles = ` .gh-portal-content { -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ - } + } + + .gh-portal-popup-container.fullscreen .gh-portal-content { + overflow-y: visible; + max-height: unset !important; + } .gh-portal-popup-container footer { padding: 0 32px 32px; @@ -371,6 +395,11 @@ const FrameStyles = ` transition: all 0.2s ease-in-out; } + .gh-portal-popup-container.fullscreen .gh-portal-closeicon { + width: 24px; + height: 24px; + } + .gh-portal-closeicon:hover { color: var(--grey5); } @@ -675,6 +704,10 @@ const MobileStyles = ` .gh-portal-popup-wrapper.account-home .gh-portal-powered a { box-shadow: none; } + + .gh-portal-popup-container.fullscreen { + padding: 0; + } } @media (max-width: 414px) { @@ -703,7 +736,7 @@ const MobileStyles = ` border-bottom: 1px solid var(--grey10); } - .gh-portal-plan-checkbox { + div:not(.gh-portal-product-card-header) > .gh-portal-plan-checkbox { grid-column: 1 / 2; grid-row: 1 / 3; margin: 0 12px; @@ -801,6 +834,7 @@ const FrameStyle = AccountPlanPageStyles + InputFieldStyles + PlanSectionStyles + + ProductsSectionStyles + SwitchStyles + ActionButtonStyles + BackButtonStyles + diff --git a/ghost/portal/src/components/PopupModal.js b/ghost/portal/src/components/PopupModal.js index 7ac72502a0..dd890c05d7 100644 --- a/ghost/portal/src/components/PopupModal.js +++ b/ghost/portal/src/components/PopupModal.js @@ -4,7 +4,7 @@ import AppContext from '../AppContext'; import FrameStyle from './Frame.styles'; import Pages, {getActivePage} from '../pages'; import PopupNotification from './common/PopupNotification'; -import {isCookiesDisabled, getSitePrices, isInviteOnlySite} from '../utils/helpers'; +import {hasMultipleProducts, isCookiesDisabled, getSitePrices, isInviteOnlySite} from '../utils/helpers'; const React = require('react'); @@ -165,6 +165,11 @@ class PopupContent extends React.Component { pageClass = page; break; } + + if (hasMultipleProducts({site}) && (page === 'signup' || page === 'signin')) { + pageClass += ' fullscreen'; + } + const className = (hasMode(['preview', 'dev'], {customSiteUrl}) && !site.disableBackground) ? 'gh-portal-popup-container preview' : 'gh-portal-popup-container'; const containerClassName = `${className} ${popupWidthStyle} ${pageClass}`; return ( diff --git a/ghost/portal/src/components/common/PlansSection.js b/ghost/portal/src/components/common/PlansSection.js index acd9f4517d..c8a0989c97 100644 --- a/ghost/portal/src/components/common/PlansSection.js +++ b/ghost/portal/src/components/common/PlansSection.js @@ -454,7 +454,7 @@ function PlansSection({plans, showLabel = true, selectedPlan, onPlanSelect, chan } const className = getPlanClassNames({cookiesDisabled, changePlan, plans}); return ( -
+
diff --git a/ghost/portal/src/components/common/ProductsSection.js b/ghost/portal/src/components/common/ProductsSection.js new file mode 100644 index 0000000000..95d6abe8f5 --- /dev/null +++ b/ghost/portal/src/components/common/ProductsSection.js @@ -0,0 +1,337 @@ +import React from 'react'; +import Switch from '../common/Switch'; +import {isCookiesDisabled} from '../../utils/helpers'; + +export const ProductsSectionStyles = ` + .gh-portal-products { + background: var(--grey13); + margin: 40px -32px; + padding: 0 32px; + } + + .gh-portal-products-priceswitch { + display: flex; + justify-content: center; + padding-top: 32px; + } + + .gh-portal-priceoption-label { + font-size: 1.3rem; + font-weight: 600; + letter-spacing: 0.3px; + text-transform: uppercase; + margin: 0 6px; + } + + .gh-portal-products-priceswitch .gh-portal-for-switch label, .gh-portal-for-switch .container { + width: 43px !important; + } + + .gh-portal-products-priceswitch .gh-portal-for-switch .input-toggle-component, + .gh-portal-products-priceswitch .gh-portal-for-switch label:hover input:not(:checked) + .input-toggle-component, + .gh-portal-products-priceswitch .gh-portal-for-switch .container:hover input:not(:checked) + .input-toggle-component { + background: var(--grey1); + border-color: var(--grey1); + box-shadow: none; + width: 43px !important; + height: 24px !important; + } + + .gh-portal-products-priceswitch .gh-portal-for-switch .input-toggle-component:before { + height: 18px !important; + width: 18px !important; + } + + .gh-portal-products-priceswitch .gh-portal-for-switch input:checked + .input-toggle-component { + background: var(--grey1); + } + + .gh-portal-products-priceswitch .gh-portal-for-switch input:checked + .input-toggle-component:before { + transform: translateX(19px); + } + + .gh-portal-products-grid { + display: grid; + grid-template-columns: repeat(${productColumns()}, minmax(0, 1fr)); + grid-gap: 32px; + width: 100%; + max-width: 1280px; + margin: 0 auto; + padding: 32px 5vw; + } + + + .gh-portal-product-card { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + background: white; + padding: 24px 24px 18px; + border-radius: 3px; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1); + min-height: 240px; + cursor: pointer; + } + + .gh-portal-product-card.checked::before { + position: absolute; + display: block; + top: -1px; + right: -1px; + bottom: -1px; + left: -1px; + content: ""; + z-index: 999; + border: 2px solid var(--brandcolor); + pointer-events: none; + border-radius: 3px; + } + + .gh-portal-product-card.checked { + box-shadow: none; + } + + .gh-portal-product-card-header { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + } + + .gh-portal-product-name { + font-size: 1.2rem; + font-weight: 500; + line-height: 1.0em; + letter-spacing: 0.5px; + text-transform: uppercase; + margin-top: 7px; + text-align: center; + min-height: 24px; + word-break: break-word; + width: 100%; + border-bottom: 1px solid var(--grey12); + padding: 8px 0 16px; + margin-bottom: 12px; + } + + .gh-portal-product-description { + font-size: 1.4rem; + line-height: 1.5em; + text-align: center; + color: var(--grey5); + margin-bottom: 24px; + } + + .gh-portal-product-price { + display: flex; + } + + .gh-portal-product-price .currency-sign { + align-self: flex-start; + font-size: 2.0rem; + font-weight: 500; + line-height: 1.3em; + } + + .gh-portal-product-price .amount { + font-size: 3.3rem; + font-weight: 500; + line-height: 1em; + } + + .gh-portal-product-price .billing-period { + align-self: flex-end; + font-size: 1.3rem; + line-height: 1.6em; + color: var(--grey7); + letter-spacing: 0.2px; + } + + .gh-portal-product-alternative-price { + font-size: 1.15rem; + line-height: 1.6em; + color: var(--grey7); + text-align: center; + margin-top: 4px; + letter-spacing: 0.2px; + height: 18px; + } + + @media (max-width: 480px) { + .gh-portal-products { + margin: 0 -32px; + } + + .gh-portal-products-grid { + grid-template-columns: unset; + grid-gap: 20px; + padding: 32px 0; + } + + .gh-portal-product-card { + display: grid; + grid-template-columns: 1fr auto; + grid-gap: 12px; + align-items: start; + min-height: unset; + padding: 20px; + } + + .gh-portal-product-card-header { + grid-row: 1; + display: grid; + grid-template-columns: 20px auto; + } + + .gh-portal-product-name { + margin: 0; + padding: 0; + text-align: left; + border-bottom: none; + min-height: unset; + } + + .gh-portal-product-description { + grid-column: 2 / 3; + margin-bottom: 0px; + text-align: left; + } + + .gh-portal-product-price { + position: relative; + } + + .gh-portal-product-price .currency-sign { + font-size: 1.5rem; + } + + .gh-portal-product-price .amount { + font-size: 2.6rem; + } + + .gh-portal-product-price .billing-period { + position: absolute; + right: 0; + top: 24px; + font-size: 1.2rem; + } + + .gh-portal-product-card-footer { + grid-row: 1; + } + + .gh-portal-popup-container.fullscreen footer.gh-portal-signup-footer, + .gh-portal-popup-container.fullscreen footer.gh-portal-signin-footer { + padding: 0 32px !important; + margin-top: 32px; + } + + .gh-portal-product-alternative-price { + display: none; + } + } +`; + +function productColumns() { + const noOfProducts = 4; + return noOfProducts > 5 ? 5 : noOfProducts; +} + +function Checkbox({name, id, onPlanSelect, isChecked, disabled = false}) { + if (isCookiesDisabled()) { + disabled = true; + } + return ( +
+ onPlanSelect(e, id)} + disabled={disabled} + /> + +
+ ); +} + +function ProductsSection() { + return ( +
+ +
+ Monthly + + Yearly +
+ +
+
+
+ +

Free

+
Free preview
+
+
+
+ $ + 0 +
+
+
+
+
+
+ +

Bronze

+
Access to all members articles
+
+
+
+ $ + 70 + /year +
+
$7/month
+
+
+
+
+ +

Silver

+
Access to all members articles and weekly podcast
+
+
+
+ $ + 120 + /year +
+
$12/month
+
+
+
+
+ +

Gold

+
Access to all members articles, weekly podcast and exclusive interviews
+
+
+
+ $ + 1000 + /year +
+
$12/month
+
+
+
+
+ ); +} + +export default ProductsSection; diff --git a/ghost/portal/src/components/pages/AccountHomePage.js b/ghost/portal/src/components/pages/AccountHomePage.js index ab112edfbf..c6efe08b48 100644 --- a/ghost/portal/src/components/pages/AccountHomePage.js +++ b/ghost/portal/src/components/pages/AccountHomePage.js @@ -93,10 +93,6 @@ export const AccountHomePageStyles = ` opacity: 0.6; } - .gh-portal-products:hover { - cursor: pointer; - } - .gh-portal-product-icon { width: 52px; margin-right: 12px; diff --git a/ghost/portal/src/components/pages/SignupPage.js b/ghost/portal/src/components/pages/SignupPage.js index 72b8226c2d..386e0951da 100644 --- a/ghost/portal/src/components/pages/SignupPage.js +++ b/ghost/portal/src/components/pages/SignupPage.js @@ -2,6 +2,7 @@ import ActionButton from '../common/ActionButton'; import CloseButton from '../common/CloseButton'; import AppContext from '../../AppContext'; import PlansSection from '../common/PlansSection'; +import ProductsSection from '../common/ProductsSection'; import InputForm from '../common/InputForm'; import {ValidateInputForm} from '../../utils/form'; import {getSitePrices, hasMultipleProducts, hasOnlyFreePlan, isInviteOnlySite} from '../../utils/helpers'; @@ -51,6 +52,14 @@ export const SignupPageStyles = ` margin-bottom: 0; } + .gh-portal-popup-container.fullscreen .gh-portal-signup-header { + margin-top: 6vmin; + } + + .gh-portal-popup-container.fullscreen .gh-portal-signin-header { + margin-top: 22vmin; + } + .gh-portal-signup-message { display: flex; justify-content: center; @@ -83,6 +92,16 @@ export const SignupPageStyles = ` background-attachment: local,local,scroll,scroll; } + .gh-portal-popup-container.fullscreen .gh-portal-content.signup, + .gh-portal-popup-container.fullscreen .gh-portal-content.signin { + width: 100%; + } + + .gh-portal-popup-container.fullscreen .gh-portal-input-section { + max-width: 420px; + margin: 0 auto; + } + .gh-portal-content.signup.invite-only { background: none; } @@ -93,6 +112,17 @@ export const SignupPageStyles = ` height: 132px; } + .gh-portal-popup-container.fullscreen footer.gh-portal-signup-footer, + .gh-portal-popup-container.fullscreen footer.gh-portal-signin-footer { + padding: 0; + width: 100%; + max-width: 420px; + } + + .gh-portal-popup-container.fullscreen footer.gh-portal-signin-footer { + padding-top: 24px; + } + .gh-portal-content.signup, .gh-portal-content.signin { max-height: calc(100vh - 12vw - 140px); @@ -350,6 +380,14 @@ class SignupPage extends React.Component { ); } + renderProducts() { + return ( + <> + + + ); + } + renderLoginMessage() { const {brandColor, onAction} = this.context; return ( @@ -379,18 +417,34 @@ class SignupPage extends React.Component {
); } - return ( -
-
- this.handleInputChange(e, field)} - onKeyDown={(e, field) => this.onKeyDown(e, field)} - /> - {this.renderPlans()} -
-
- ); + + if (hasMultipleProducts({site})) { + return ( +
+
+ this.handleInputChange(e, field)} + onKeyDown={(e, field) => this.onKeyDown(e, field)} + /> + {this.renderProducts()} +
+
+ ); + } else { + return ( +
+
+ this.handleInputChange(e, field)} + onKeyDown={(e, field) => this.onKeyDown(e, field)} + /> + {this.renderPlans()} +
+
+ ); + } } renderSiteLogo() { diff --git a/ghost/portal/src/utils/fixtures.js b/ghost/portal/src/utils/fixtures.js index 834ae1bb6b..249693336c 100644 --- a/ghost/portal/src/utils/fixtures.js +++ b/ghost/portal/src/utils/fixtures.js @@ -85,8 +85,8 @@ const products = [ export const site = { title: 'A Ghost site', description: 'Thoughts, stories and ideas.', - logo: 'https://pbs.twimg.com/profile_images/1111773508231667713/mf2N0uqc_400x400.png', - icon: 'https://pbs.twimg.com/profile_images/1111773508231667713/mf2N0uqc_400x400.png', + logo: 'https://static.ghost.org/v4.0.0/images/ghost-orb-1.png', + icon: 'https://static.ghost.org/v4.0.0/images/ghost-orb-1.png', accent_color: '#45C32E', url: 'http://localhost:2368/', plans: { @@ -96,7 +96,7 @@ export const site = { }, products, prices: prices, - allow_self_signup: true, + allow_self_signup: false, members_signup_access: 'all', free_price_name: 'Free', free_price_description: 'Free preview',