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

Plans Grid: add monthly pricing option #48963

Merged
merged 57 commits into from Jan 28, 2021
Merged

Conversation

ciampo
Copy link
Contributor

@ciampo ciampo commented Jan 15, 2021

Changes proposed in this Pull Request

  • Add the <PlansIntervalToggle> component to the Plans Grid UI
  • Add various UI elements to the Plans Grid (both table and accordion variations) related to monthly plans
  • Rewrite the Feature List component, in order to allow any feature to be showing the "requires annually plan" badge
  • Hook the UI to the plans data-store, using the billing period selected by the user (monthly or annually) and update the plans accordion / table accordingly
  • Updated Step by Step launch flow, so that plan info is displayed correctly in the final checkout step. When the monthly plan is selected, the cost of the premium domain is displayed in the final step too (plus minor style fixes)
  • Update the refund window (14 or 7 days) in the plans step in Gutenboarding, based on the value picked by the user when interacting with the plans grid toggle

Testing instructions

Setup

Test in Gutenboarding

Test in Focused Launch Flow

  • Prepare your sandbox:
    • Make sure you have an active ssh connection to your sandbox
    • Clear your sandbox and pull the latest version from trunk
    • Add an unlaunched site created via /start to your sandbox
  • Pull this PR's branch on your local machine and run the project locally:
    • Run yarn && yarn start in the root folder
    • After the command above has finished compiling, in a separate terminal window run cd apps/editing-toolkit && yarn dev --sync
  • Visit calyspo.localhost:3000/page/UNLAUNCHED_SITE_CREATED_WITH_START.wordpress.com/home?flags=create/focused-launch-flow
  • Click on the "Launch" button to open Focused Launch flow
  • Click on the "View all Plans" button to navigate to the Plan Details step
  • Make sure that all A/Cs from Plans Grid: add monthly pricing #48760 are satisfied (except the follow up/related issues)

Test in Step By Step Launch Flow

  • Prepare your sandbox:
    • Make sure you have an active ssh connection to your sandbox
    • Clear your sandbox and pull the latest version from trunk
    • Add an unlaunched site created via /new and on a free plan to your sandbox
  • Pull this PR's branch on your local machine and run the project locally:
    • Run yarn && yarn start in the root folder
    • After the command above has finished compiling, in a separate terminal window run cd apps/editing-toolkit && yarn dev --sync
  • Visit calyspo.localhost:3000/page/UNLAUNCHED_SITE_CREATED_WITH_NEW .wordpress.com/home
  • Click on the "Launch" button to open Step By Step Launch flow
  • Proceed to the plans step
  • Make sure that all A/Cs from Plans Grid: add monthly pricing #48760 are satisfied (except the follow up/related issues)
  • Make sure that checkout step looks correct (all of the listed features are correctly included in the selected plan, including a custom domain in case of annually-billed plans)

Fixes #48760
Fixes #49027

@ciampo ciampo added [Feature] Plans & Upgrades All of the plans on WordPress.com and flow for upgrading plans. [Status] In Progress [Goal] New Onboarding previously called Gutenboarding Focused Launch Issues and PRs related to Focused Launch labels Jan 15, 2021
@ciampo ciampo self-assigned this Jan 15, 2021
@matticbot
Copy link
Contributor

@matticbot
Copy link
Contributor

matticbot commented Jan 15, 2021

Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

App Entrypoints (~1661 bytes added 📈 [gzipped])

name                 parsed_size           gzip_size
entry-gutenboarding      +6434 B  (+0.4%)    +1661 B  (+0.3%)

Common code that is always downloaded and parsed every time the app is loaded, no matter which route is used.

Legend

What is parsed and gzip size?

Parsed Size: Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
Gzip Size: Compressed size of the JS and CSS files. This much data needs to be downloaded over network.

Generated by performance advisor bot at iscalypsofastyet.com.

@ciampo
Copy link
Contributor Author

ciampo commented Jan 15, 2021

Update on the progress so far:

image
image

Done

  • Added the Monthly / Annually toggle component to the plans grid
  • Mocked some missing data from data-store
  • Started work on implementing UI changes to the accordion version of the plans grid:
    • Changed the billing information below the price to Per month, billed monthly / Per month, billed as [PRICE] annually
    • Added the SAVE [PERC]% BY PAYING ANNUALLY text below the plan price (marked with number 1 in the screenshot above)
    • Added the INCLUDED WITH ANNUAL PLANS text above the domain item in the feature list (marked with number 2 and 5 in the screenshot above). I took inspiration from how this was implemented in /start/plans, since it was missing from the design specs.

Progress proceeded more slowly than expected, as some parts of the UI had to be refactored to allow for different outcomes depending on the billing period (monthly vs annually)

What's left

  • Integration with plans data store (once Data stores: implement monthly plans fetching #48790 gets merged). In particular, we need to pull the correct data about prices, discounts (per plan), and maximum discount value.
  • Apply same UI changes to the "Table" variant of the plans-grid.
  • It also looks like the plans data from the data-store doesn't include, for annually billed plans, the total cost of the plan for one year. Currently in the UI I'm using the monthly cost because I couldn't find the annual cost (see number 4 in the screenshot above).
  • By looking at /start/plans, it seems that the "Live chat support" feature is also not included with the monthly plans. From a quick look at the plans data-store, it looks like we don't have a way of knowing if a certain feature is not included with the monthly version of a plan. Furthermore, we'd also need to slightly change the way this data is passed down to the UI, since at the moment features are just an array of strings.
  • The plan details component, which shows a detailed comparison of all plans feature-by-feature, also needs to be updated reflecting that Custom domain (starting from Personal plan) and Live chat support (starting from Premium plan) are not included in the monthly version of a paid plan.
  • Finally, a note about the feature list layout — by adding the INCLUDED WITH ANNUAL PLANS, the spacing between the feature list items becomes irregular, since domain item now takes more vertical space (see number 3 in the screenshot above). One way of tackling this issue would be to set align-self: end; on each child element on the CSS grid

cc @razvanpapadopol

aria-label={
billingInterval === 'ANNUALLY'
? __( 'Included with annual plans', __i18n_text_domain__ )
: __( 'Only included with annual plans', __i18n_text_domain__ )
Copy link

Choose a reason for hiding this comment

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

ℹ️ String reuse speeds up translation and improves consistency. The following string might make a good alternative and has already been translated 17 times:
translate( 'Included with annual plans' ) ES Score: 9

@ciampo ciampo force-pushed the feat/plans-grid/monthly-prices branch from 21d9c57 to 2f76ed0 Compare January 19, 2021 10:43
@ciampo
Copy link
Contributor Author

ciampo commented Jan 19, 2021

Rebased on top of latest trunk and solved conflicts

{ ! isFree &&
( billingInterval === 'ANNUALLY'
? sprintf(
__( 'per month, billed as %s annually', __i18n_text_domain__ ),
Copy link

Choose a reason for hiding this comment

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

ℹ️ String reuse speeds up translation and improves consistency. The following string might make a good alternative and has already been translated 3 times:
translate( 'per month{{br/}}billed yearly' ) ES Score: 7

>
{ sprintf(
// Translators: "%s" is a number, and "%%" is the percent sign. Please keep the "%s%%" string unchanged when translating.
__( 'Save %s%% by paying annually', __i18n_text_domain__ ),
Copy link

Choose a reason for hiding this comment

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

ℹ️ String reuse speeds up translation and improves consistency. The following string might make a good alternative and has already been translated 17 times:
translate( 'Save %(discountRate)s%% by paying annually' ) ES Score: 8

@ciampo
Copy link
Contributor Author

ciampo commented Jan 20, 2021

Hey @ollierozdarz , we’ve been working on the UI changes to enable monthly plans in Gutenboarding (and Focused Launch and Step by Step Launch).

So far we followed the “Onboarding” and “Launch flow” design specs on Figma, but in a few cases we had to go with our own judgment — mainly because of some features that are supported in the reskinned signup & launch flows.

One thing to keep in mind is that the “Plans Grid” package is re-used across different flows (gutenboarding, step by step launch, and focused launch), and so the changes that we make are going to be applied across all these flows.

We would like you to visit the staging link and give some early feedback on this version of the plans grid in Gutenboarding.

In particular, these are some items that we’d like your feedback on:

  • We’ve added the “INCLUDED WITH ANNUAL PLANS” text above all features that require the annual version of a plan. We followed the implementation from the reskinned signup/launch flows, but we changed a few details in order to match more closely with the style of this new UI (e.g. we’re using orange instead of red for the text, we’re striking through the original grey text, and we’re showing an orange cross icon when the feature is not included)
  • We added the same “INCLUDED WITH ANNUAL PLANS” text also in the comparison table at the bottom of the page. When the monthly version of a plan is selected, the ticks are turned into crosses
  • We changed the “SAVE X%” text to “SAVE X% BY PAYING ANNUALLY” to achieve feature parity with the reskinned signup/launch flows
  • The feature items in each plan’s card have green ticks, although we changed the green to be the same as the “SAVE X% BY PAYING ANNUALLY” text
  • Following the latest Figma specs, the interactive “custom domain” item (the first in the list of features) has dark grey text. This is different from what’s currently in production (that text is blue instead of gray)

As a caveat, please keep in mind that at the moment the data for monthly plans has not been integrated yet, so please ignore the figures (prices and discounts) about monthly plans during your review (you can actually see the complete list of TODO items at the top of this page).

Here's also a screen capture, in case the staging link doesn't work for you:

monthly-plans-grid.mp4

cc @razvanpapadopol

@ollierozdarz
Copy link

Hi @ciampo, thanks for the ping. First of all, great job on this! 👏

Rick has asked me to take a look at giving this specific page some more love in the near future (specifically the plans accordion), so I'm not keen to change much here now, and I think this is nearly at a state where it's at parity to ship.

I did notice a few small things that could be improved and listed them below:

Screen Shot 2021-01-21 at 12 03 12 pm

Screen Shot 2021-01-21 at 12 03 16 pm

Screen Shot 2021-01-21 at 12 03 23 pm

For the note above, I never specified this in my refined reskin onboarding Figma files (my bad! 🙂), but I think when this link is active we should underline it to make it stand out more (i.e. the user is able to select a URL since they have Annual toggled and the correct plan).

Screen Shot 2021-01-21 at 12 07 48 pm

For the After screenshot, I've just aligned the checks and crosses with the feature label (for consistency) and added more bottom margin to the 'Included with annual plans', since they were sitting very close to the text below. While we're here, we may as well fix the border-radius for the primary container (it should be using the same [looks like 5px] on all four corners).

@paulbonahora
Copy link

Great work on this! I'd like to add some further feedback:

  • Domain selection step: replace "included in plans" for "included on annual plans"
  • Refund policy at the top of plans selection page: annual plans support 30 days (soon to be 14 days, we'll have to update this on Friday so it sounds like it's good timing to refine this - didn't have this on my radar as part of the 14 days project). Refund policy for monthly plans is 7 days. The message could change depending on whether the user selects monthly or yearly, just to be clearer to the user: "There is no risk. You can cancel your annual plan for a full refund within 14 days" or "There is no risk. You can cancel your monthly plan for a full refund within 7 days".
  • Discounts shown for annual plans (the 43%) will vary slightly per currency, just as an FYI.

@ciampo
Copy link
Contributor Author

ciampo commented Jan 21, 2021

Thank you @ollierozdarz and @paulbonahora for your feedback!

Here's some quick notes in response to @ollierozdarz 's feedback:

  • The border radius and the small dark outline in the "Annually"/"Monthly" toggle are some weird glitches that are not supposed to be there. I'll have a look and fix those
  • Noted re. underlining the "domain" link when it's active, and using a darker shade of grey
  • Noted re. aligning the check/cross with the feature label
  • Noted re. adding more bottom margin to the "'Included with annual plans'" text
  • Noted re. increasing the border-radius of the plan containers to 5px

And here's some quick notes in response to @paulbonahora 's feedback:

  • Noted re. replacing "included in plans" for "included on annual plans"
  • Noted re. rewording the refund policy at the top of the plans page
  • Regarding the discount figures (and other data about the monthly plans), please note that this PR is still WIP and that those figures at the moment are just placeholders. They will likely be updated today and use real-world, dynamic data form the APIs

@ciampo ciampo force-pushed the feat/plans-grid/monthly-prices branch from a9f4253 to 451a00a Compare January 21, 2021 15:00
@ciampo
Copy link
Contributor Author

ciampo commented Jan 21, 2021

Update:

@ciampo ciampo force-pushed the feat/plans-grid/monthly-prices branch from 1d4e0e4 to 61f1d38 Compare January 22, 2021 08:53
@ciampo
Copy link
Contributor Author

ciampo commented Jan 22, 2021

Update:

  • rebased on top of latest trunk
  • refactored some data-store related code:
    • aggregated selectors into same useSelect hook call
    • moved features data processing to data store
    • added features sorting, so that features that require the annually billed version of a plan are first

@ciampo
Copy link
Contributor Author

ciampo commented Jan 25, 2021

Update:

@ciampo ciampo marked this pull request as ready for review January 25, 2021 16:52
@ciampo ciampo added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. and removed [Status] In Progress labels Jan 25, 2021
@ciampo
Copy link
Contributor Author

ciampo commented Jan 25, 2021

Update:

  • Fixed code to retrieve the selected plan product in the Step by Step flow (checkout step)
    • also updated how features are displayed
    • also fixed some minor CSS glitches
  • Reported this issue in the Step by Step final (checkout) step — we can start reviewing this PR while we agree on the best way to get around it

…annually

- refactor all calls to LaunchStore into one useSelect
- get the plan product from the PlanStore, useful to get the slug and billingPeriod
- show only the effective features that come with the selected plan
- fix tick icon sizing (it would shrink on small viewports)
This prevents that text from overlapping with action buttons in step by step flow
It was deleted by mistake during a rebase
@ciampo ciampo force-pushed the feat/plans-grid/monthly-prices branch 2 times, most recently from 0ea59ec to f7487a8 Compare January 27, 2021 21:55
Rename "doesFeatureRequireAnnuallyBilledPlan" to "featureRequiresAnnual"

Fix typo: Monhtly => Monthly

Refactor maxMonthlyDiscountPercentage truthy check (+ typo)

Refactor maxMonthlyDiscountPercentage truthy check

Typo
Fix: wrap { disabledLabel > inside a React fragment to avoid render errors

Use strings as text nodes instead of react fragments
Fix translations: use same strings as /start for plans toggle

Fix translations: use same strings as /start form "SAVE X% BY PAYING ANUALLY"

Add "Domain Registration" string in step by step launch final step

Fix translations: "per month, billed as %s annually" => "billed annually"

This is because there are already translations matching what's in /start

Fix translations: use double percent sign to avoid sprintf errors
… plans are selected

Translations fix: remove "billed yearly" from bottom of details plan

Translations fix: remove (billed yearly) from comparison table only for monthly plans
@ciampo ciampo force-pushed the feat/plans-grid/monthly-prices branch from f7487a8 to 948c222 Compare January 28, 2021 08:07
Copy link

@razvanpapadopol razvanpapadopol left a comment

Choose a reason for hiding this comment

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

Tested /new in EN and FR and it looks good. I guess we'll re-test the ET before the next version release.
🚢

@ciampo ciampo merged commit 52b07a5 into trunk Jan 28, 2021
@ciampo ciampo deleted the feat/plans-grid/monthly-prices branch January 28, 2021 09:37
@matticbot matticbot removed the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Jan 28, 2021
@paulbonahora
Copy link

It looks like there's confusion with the wording on /new/plans page at the very bottom of the page when the yearly option is selected. See screenshot here.

I'd suggest replacing the wording "Monthly Subscription (billed yearly)" to "Monthly Price (billed yearly)" for clarity. There's no change needed when the toggle is set to monthly.

cc: @simison

__i18n_text_domain__
),
maxSavingsPerc
{ maxDiscount: maxMonthlyDiscountPercentage ?? 0 }
Copy link
Member

Choose a reason for hiding this comment

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

Seems like we're checking for maxMonthlyDiscountPercentage above, so it will never be null / undefined, therefore there should be no need for the nullish coalescing I think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Editing Toolkit For issues and PRs that affect the Editing Toolkit plugin [Feature] Plans & Upgrades All of the plans on WordPress.com and flow for upgrading plans. Focused Launch Issues and PRs related to Focused Launch [Goal] New Onboarding previously called Gutenboarding Launch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Plans Grid: domain CTA chevron down icon should not be green Plans Grid: add monthly pricing
8 participants