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

Update theme tier badges in Theme Details and Theme Showcase (LiTS & LoTS) #98451

Open
wants to merge 22 commits into
base: trunk
Choose a base branch
from

Conversation

abotic
Copy link
Member

@abotic abotic commented Jan 16, 2025

Related to:

Proposed Changes

  • Improved badge visibility in theme details page to match theme grid design
  • Added clear hierarchy for badge display:
    • Shows Free badge for free themes when user is not logged in
    • Shows Included with plan badge for themes available in user's current plan
    • Shows Available on {plan name} for themes requiring higher tier plans
    • Shows Available on Business for WooCommerce themes
    • Shows Available on Business (and price €X.XX/month where applicable) for partner themes
    • Shows correct plan upgrades for Bundled and Community themes
  • Updated badge positioning to appear above theme title
  • Removed style variations from theme grid view
  • Unified badge styling across theme showcase and details pages
  • Refactor components with memoization and selector optimizations

Why are these changes being made?

Currently, the theme details page doesn't clearly indicate which plan is required for themes, leading to user confusion. This update improves clarity by:

  1. Making badge visibility consistent between grid and details views
  2. Clearly indicating when a theme is included in the user's current plan
  3. Specifically showing which plan tier is needed (Personal, Premium, Business, etc.)
  4. Providing clear pricing information for partner themes

Testing Instructions

  1. Test each scenario in both Theme Showcase grid and Theme Details page
  2. Test with both logged-in and logged-out states where applicable
Theme Type Login State Location Expected Behavior
Active theme Logged in Grid Shows "Active" badge
Free theme Logged out Grid & Details Shows "Free" badge above title
Personal plan theme Logged in (no plan) Grid & Details Shows "Available on Personal"
Premium plan theme Logged in (no/lower plan) Grid & Details Shows "Available on Premium"
WooCommerce plan theme Logged in (no/lower plan) Grid & Details Shows "Available on Business"
Partner theme Logged in (no Business plan) Grid & Details Shows "Available on Business" (and price €X.XX/month where applicable)
Partner theme Logged in (Business plan) Grid & Details Shows "€X.XX/month"
Bundled theme Logged in (no/lower plan) Grid & Details Shows "Available on Business"
Bundled theme Logged in (Business plan) Grid & Details Shows "Included with plan"
Community theme Logged in (no/lower plan) Grid & Details Shows "Community" + "Available on Business"
Community theme Logged in (Business plan) Grid & Details Shows "Community" + "Included with plan"
Included plan theme Logged in (with plan) Grid & Details Shows "Included with plan"
Before After
before.mov
after.mov

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • Have you written new tests for your changes?
  • Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
  • Have you checked for TypeScript, React or other console errors?
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
  • For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?

@abotic abotic added [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. Testing labels Jan 16, 2025
@abotic abotic requested a review from a team January 16, 2025 01:22
@abotic abotic self-assigned this Jan 16, 2025
@matticbot
Copy link
Contributor

matticbot commented Jan 16, 2025

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

App Entrypoints (~149 bytes removed 📉 [gzipped])

name                   parsed_size           gzip_size
entry-subscriptions         -509 B  (-0.0%)     -147 B  (-0.0%)
entry-stepper               -393 B  (-0.0%)     -119 B  (-0.0%)
entry-main                  -393 B  (-0.0%)     -115 B  (-0.0%)
entry-login                 -393 B  (-0.0%)     -116 B  (-0.0%)
entry-domains-landing       -393 B  (-0.1%)     -116 B  (-0.1%)
entry-browsehappy           -393 B  (-0.2%)     -116 B  (-0.2%)

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

Sections (~2622 bytes removed 📉 [gzipped])

name                                parsed_size           gzip_size
themes                                  -4800 B  (-0.5%)     -931 B  (-0.3%)
theme                                   -2936 B  (-0.4%)     -526 B  (-0.2%)
promote-post-i2                          -156 B  (-0.0%)      -85 B  (-0.0%)
patterns                                  -13 B  (-0.0%)      +12 B  (+0.0%)
import-hosted-site-flow                   -13 B  (-0.0%)      -17 B  (-0.0%)
import                                    -13 B  (-0.0%)      -15 B  (-0.0%)
a8c-for-agencies-partner-directory        -13 B  (-0.0%)      -15 B  (-0.0%)

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.

Async-loaded Components (~1138 bytes removed 📉 [gzipped])

name                                                                         parsed_size           gzip_size
async-load-signup-steps-theme-selection                                          -4787 B  (-1.4%)     -916 B  (-0.9%)
async-load-design-blocks                                                         -4787 B  (-0.2%)     -916 B  (-0.2%)
async-load-comment-block-editor                                                    -13 B  (-0.0%)       +6 B  (+0.0%)
async-load-automattic-global-styles-src-components-global-styles-variations        -13 B  (-0.0%)      -19 B  (-0.0%)

React components that are loaded lazily, when a certain part of UI is displayed for the first time.

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.

@mikachan mikachan mentioned this pull request Jan 16, 2025
15 tasks
@mikachan mikachan linked an issue Jan 16, 2025 that may be closed by this pull request
1 task
Copy link
Member

@mikachan mikachan left a comment

Choose a reason for hiding this comment

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

I'm having a go at reviewing this based on spending some time implementing the new designs mentioned here.

These changes look great so far when comparing them to the above designs, including all the different tiers.

One potential change I noticed is that I believe any free themes should always show a "free" badge, rather than the "included with plan" badge, e.g. TT5 and LeanCV in this screenshot:

image

@mikachan
Copy link
Member

I'd also like to highlight this comment from @jeryj:

It looks like the "Available on ____" badge work and removing tooltips has already been done behind the isGoalsAtFrontExperiment flag in #97655. If we're set on shipping this design, I think a lot of the work will just be to remove the isGoalsAtFrontExperiement.

I'm wondering if that should be part of this PR, or maybe it could be done in a separate branch?

@matticbot
Copy link
Contributor

matticbot commented Jan 22, 2025

This PR modifies the release build for the following Calypso Apps:

For info about this notification, see here: PCYsg-OT6-p2

  • blaze-dashboard
  • command-palette-wp-admin
  • help-center
  • newsletter
  • notifications
  • odyssey-stats
  • whats-new
  • wpcom-block-editor

To test WordPress.com changes, run install-plugin.sh $pluginSlug update/theme-tier-badges-changes on your sandbox.

@abotic
Copy link
Member Author

abotic commented Jan 22, 2025

I'm having a go at reviewing this based on spending some time implementing the new designs mentioned here.

These changes look great so far when comparing them to the above designs, including all the different tiers.

One potential change I noticed is that I believe any free themes should always show a "free" badge, rather than the "included with plan" badge, e.g. TT5 and LeanCV in this screenshot:

image

Thanks for taking a look @mikachan ! I was thinking about this exact point - the "Free" vs "Included" badge choice for Free themes.

The reasoning behind "Included" badge that I went with was just to help users better appreciate the whole package when they are on a Personal+ plan, even if some themes would be free anyway.

But you raise a really good point about clarity. What's your take on which would be more intuitive for users?
@fditrapani , do you maybe have thoughts on which approach we should go with?

@fditrapani
Copy link
Contributor

@fditrapani , do you maybe have thoughts on which approach we should go with?

Thanks for bringing this up. It's a great point. I think it's worthwhile to delineate between the free themes and what's included in your plan. I support making that change!

@abotic
Copy link
Member Author

abotic commented Jan 22, 2025

I'd also like to highlight this comment from @jeryj:

It looks like the "Available on ____" badge work and removing tooltips has already been done behind the isGoalsAtFrontExperiment flag in #97655. If we're set on shipping this design, I think a lot of the work will just be to remove the isGoalsAtFrontExperiement.

I'm wondering if that should be part of this PR, or maybe it could be done in a separate branch?

@mikachan Thanks for flagging this. I agree this should be handled in a separate PR to keep the current changes focused.

Also, found a bug with community theme badges that needs fixing in some underlying code and state. I'll have it fixed in the next commit and we can do another round of testing/review if possible.

@fditrapani
Copy link
Contributor

Thanks for putting this PR together, it's looking great! This might still be in progress but just wanted to point out that when I look at partner themes on a business site, it's saying they're included in my plan:

image

In these cases, can we show the monthly price:
image

@fditrapani
Copy link
Contributor

hey folks, just checking in to see how this is going and if there's anything I can do to unblock it if we're blocked?

@abotic
Copy link
Member Author

abotic commented Jan 29, 2025

hey folks, just checking in to see how this is going and if there's anything I can do to unblock it if we're blocked?

Hi @fditrapani , I was blocked on other task that took some time to resolve. Jumping on this one today and will try to get it ready as soon as possible.

@fditrapani
Copy link
Contributor

Awesome. Thanks for the update @abotic!

- Fix partner theme price display logic for business plan
- Add proper theme bundle/partner price handling
- Refactor components with proper memoization and selector optimizations
- Clean up unused imports and tooltip logic
- Add proper equality checks to prevent unnecessary rerenders
- Fix theme upgrade/included badge conditional rendering
- Fix partner theme price display logic for business plan
- Add proper theme bundle/partner price handling
- Refactor components with proper memoization and selector optimizations
- Clean up unused imports and tooltip logic
- Add proper equality checks to prevent unnecessary rerenders
- Fix theme upgrade/included badge conditional rendering
@abotic
Copy link
Member Author

abotic commented Jan 31, 2025

Hi @fditrapani and @mikachan 👋

Thank you for your comments, I've made some changes and it is ready for review.

Recent changes:

  • Fixed all review comments
  • Updated bundled/community/partner theme badge display
  • Added price display for partner themes on Business plan
  • Cleaned up unused code
  • Refactored components for better performance with memoization and selector optimizations

Updated testing instructions/table and added new video showing free and business plan showcase (Personal and Premium follow same pattern).

Looking forward to your feedback.

@abotic abotic requested review from mikachan and fditrapani February 1, 2025 11:32
@fditrapani
Copy link
Contributor

Thanks for making these updates @abotic! It's getting really close. I'll let you decide whether you want to merge this and work on the following tweaks as a follow up:

Upgrade badge font
The upgrade badge's font is incorrect. It's using Recoletta like the title but should be the standard sans-serif font we use for body copy:

image

here's how it should look:
image

Remove partner badge
Now that we're presenting the plans and pricing better, the partner badge feels redundant. Can we remove it from the listings:

image

and the theme details page:
image

The same goes for the WooCommerce badge:
image

We have a filter for that, so labelling it isn't as necessary.

Copy link
Contributor

@xavier-lc xavier-lc left a comment

Choose a reason for hiding this comment

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

LGTM!

@mmtr
Copy link
Member

mmtr commented Feb 10, 2025

Is it expected that badges are not consistent between the logged-in Theme Showcase and the onboarding's Design Picker?

Page Before After
Theme Showcase Screenshot 2025-02-10 at 15 57 14 Screenshot 2025-02-10 at 15 55 29
Design Picker Screenshot 2025-02-10 at 15 45 40 Screenshot 2025-02-10 at 15 45 43

@fditrapani
Copy link
Contributor

Good catch @mmtr. That looks like a regression. They should be the same.

@dsas
Copy link
Contributor

dsas commented Feb 14, 2025

@abotic, popping this back out of Ready To merge for the inconsistency to be looked at

@abotic
Copy link
Member Author

abotic commented Feb 14, 2025

@fditrapani @mmtr Same styling applied on onboarding as well. Thanks for feedback!

Please note that there was one minor regression issue with plans that had pricing shown near them.
There seems to be too much text in badge when we are previewing a theme while we are on onboarding.

We could change the font, apply some margins while being onboarded or something else, but changing the "plus" to "+" seemed to me like a best option to keep exactly same styling between onboarding and logged-in theme picker. If this is not okay, please let me know some other idea we could apply here.

Example:

Before After
Screenshot 2025-02-14 at 15 46 52 Screenshot 2025-02-14 at 15 46 25

@fditrapani
Copy link
Contributor

Thanks for the updates. We can save even more space, for this specific case, if we update it to "On Business + $10.00/month"

@mmtr
Copy link
Member

mmtr commented Feb 17, 2025

Maybe a design nitpick, but I noted that the badges in the Design Picker look bigger now because the font-size has been increased to 14px:

Screenshot 2025-02-17 at 16 05 54 Screenshot 2025-02-17 at 16 04 28

Currently, in production, the font-size is set to 12px which also matches the font-size used in the Figma design I can find in p9Jlb4-fea-p2.

This makes me think that the font-size increase has not been intentional.

@mmtr
Copy link
Member

mmtr commented Feb 17, 2025

Community themes also show a weird layout, is this expected?
Screenshot 2025-02-17 at 16 16 08

@mmtr
Copy link
Member

mmtr commented Feb 17, 2025

Another issue is that the theme name may be hidden by badges:

Before After
Screenshot 2025-02-17 at 16 20 06 Screenshot 2025-02-17 at 16 20 11

@fditrapani
Copy link
Contributor

Thanks for bringing up these extra issue @mmtr!

Maybe a design nitpick, but I noted that the badges in the Design Picker look bigger now because the font-size has been increased to 14px:

Great catch. As you noted, this is impacting the space we have to display the theme name.

Community themes also show a weird layout, is this expected?

Given that we have a community filter. This badge is unclear. Can we remove it since we show it on the theme details page:

image

Another issue is that the theme name may be hidden by badges

Likewise with the Sensei and other badges. We're trying to do too much on this screen all at once. People can find these types of themes with a search or the filters if they're looking for them. Otherwise, they don't really mean much.

@abotic
Copy link
Member Author

abotic commented Feb 18, 2025

@mmtr @fditrapani Thanks for great regression testing!
Everything discussed since the last commit has been fixed/changed.

That includes issue with a fonts, overlapping of elements and extra badges. We have now removed extra badges (community, bundle, WooCommerce) from theme showcase, but they are still available in theme details.

Please let me know if you find anything else.

@fditrapani
Copy link
Contributor

Thanks for these updates @abotic. We're almost there! I did one final pass on everything across the /themes, onboarding, and the theme marketplace within a site. The only thing I found now is that when you're on a business plan, we show the price in a black pill:

image

Can we show it as regular text with the price like all the others:
image

The same on the theme details, we only show the price in the dark pill:
image

Can we add a star in there like all the other upgrades and add some text to not make it feel so transactional since we have the space :)
image

@abotic
Copy link
Member Author

abotic commented Feb 19, 2025

@fditrapani Everything you proposed regarding pricing has been implemented and pushed.
There were a few minor bugs with font sizes in the included and free plans getting overridden in some edge cases, so I fixed those as well.

Let me know if there's anything else you would like to change/improve, and I can jump on it immediately :)

Copy link
Contributor

@fditrapani fditrapani left a comment

Choose a reason for hiding this comment

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

Thank you for all the updates @abotic! This looks great now.

Copy link
Member

@mmtr mmtr left a comment

Choose a reason for hiding this comment

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

One thing that caught my attention is that it seems that the theme title and the badge are not aligned (I added some read/blue lines to better note it):

Screenshot 2025-02-19 at 19 30 02

Feel free to ignore this feedback if you believe this is something not important.

isThemePurchased( state, themeId, siteId )
const themeType = useSelector(
( state ) => getThemeType( state, themeId ),
( prev, next ) => prev === next
Copy link
Member

Choose a reason for hiding this comment

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

Is this needed? I always thought this was the default behavior:

useSelector() only forces a re-render if the selector result appears to be different than the last result. The default comparison is a strict === reference comparison.
https://react-redux.js.org/api/hooks#equality-comparisons-and-updates

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, you're absolutely right! The custom equality function (prev, next) => prev === next is redundant since it's identical to useSelector's default behavior.

I'll remove it and simplify to just:

const themeType = useSelector(state => getThemeType(state, themeId));

Thanks for catching this!

Comment on lines -30 to -53
const getTooltipMessage = () => {
if ( ! isEcommerceTrialMonthly ) {
return createInterpolateElement(
translate(
'This community theme can only be installed if you have the <Link>%(businessPlanName)s plan</Link> or higher on your site.',
{ args: { businessPlanName: getPlan( PLAN_BUSINESS )?.getTitle() ?? '' } }
),
{
Link: <ThemeTierBadgeCheckoutLink plan={ planTooltipName } />,
}
);
}
if ( isEcommerceTrialMonthly ) {
return createInterpolateElement(
translate(
"This theme can't be installed on a trial site. Please upgrade to the <Link>%(ecommercePlanName)s plan</Link> to install this theme.",
{ args: { ecommercePlanName: getPlan( PLAN_ECOMMERCE )?.getTitle() ?? '' } }
),
{
Link: <ThemeTierBadgeCheckoutLink plan={ planTooltipName } />,
}
);
}
};
Copy link
Member

Choose a reason for hiding this comment

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

This causes a confusing badge now for trial plans.

For instance, on a site with an Commerce trial plan, we now say the theme is available on the Business plan, but they cannot really buy that plan (they can only buy the Commerce non-trial plan):

Before After
Screenshot 2025-02-19 at 19 54 33 Screenshot 2025-02-19 at 19 54 41

On these cases, we should say "Available on the Commerce plan" instead of "Available on the Business plan".

Comment on lines -45 to -67
if ( isPartnerThemePurchased && ! isThemeAllowed && ! isEcommerceTrialMonthly ) {
return createInterpolateElement(
translate(
'You have a subscription for this theme, but it will only be usable if you have the <link>%(businessPlanName)s plan</link> or higher on your site.',
{ args: { businessPlanName: getPlan( PLAN_BUSINESS )?.getTitle() ?? '' } }
),
{
Link: <ThemeTierBadgeCheckoutLink plan={ planTooltipName } />,
}
const priceBadge = useMemo( () => {
if ( ! isThemeAllowed ) {
return (
<ThemeTierPlanUpgradeBadge
showPartnerPrice={ showPartnerPrice }
hideBackgroundOnUpgrade={ hideBackgroundOnUpgrade }
/>
);
}

if ( isPartnerThemePurchased && ! isThemeAllowed && isEcommerceTrialMonthly ) {
return createInterpolateElement(
translate(
"You have a subscription for this theme, but it isn't usable on a trial plan site. Please upgrade to the <link>%(ecommercePlanName)s plan</link> to install this theme.",
{ args: { ecommercePlanName: getPlan( PLAN_ECOMMERCE )?.getTitle() ?? '' } }
),
{
Link: <ThemeTierBadgeCheckoutLink plan={ planTooltipName } />,
}
);
}
Copy link
Member

Choose a reason for hiding this comment

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

Same for partner themes and Commerce trial sites. We cannot ask them to buy the Business plan, because their only option is the Commerce plan:

Before After
Screenshot 2025-02-19 at 19 59 11 Screenshot 2025-02-19 at 19 59 18

return fullLabel.length > MAX_LABEL_LENGTH
? /* translators: This is a shorter version of the text "Available on %(planName)s plus %(price)s/month". */
Copy link
Member

Choose a reason for hiding this comment

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

We should keep this comment since it's helpful for translators.

Comment on lines -160 to -169
<PremiumBadge
className="theme-tier-badge__content is-third-party"
focusOnShow={ false }
isClickable={ false }
labelText={ translate( 'Partner' ) }
shouldHideIcon
tooltipClassName="theme-tier-badge-tooltip"
tooltipContent={ partnerTooltipContent }
tooltipPosition="top"
/>
Copy link
Member

@mmtr mmtr Feb 20, 2025

Choose a reason for hiding this comment

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

Is it expected that the "Partner" badge is now not displayed in the theme details view?

Before After
Screenshot 2025-02-20 at 11 22 43 Screenshot 2025-02-20 at 11 23 02

Asking because this is inconsistent with the "Community" or "WooCommerce" badges:

Before After
Screenshot 2025-02-20 at 11 36 25 Screenshot 2025-02-20 at 11 36 40
Screenshot 2025-02-20 at 11 37 24 Screenshot 2025-02-20 at 11 37 29

@@ -472,6 +472,7 @@ const UnifiedDesignPickerStep: Step = ( { navigation, flow, stepName } ) => {
const getBadge = ( themeId: string, isLockedStyleVariation: boolean ) => (
<ThemeTierBadge
canGoToCheckout={ false }
isThemeShowcase
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick (non-blocking): This is a bit confusing, because the unified-design-picker.tsx file is part of the Design Picker, not the Theme Showcase.

What are you trying to achieve when isThemeShowcase is true? It seems that the intention is to support two different styles, one for when there is a list of themes and another one for when only one theme is visible.

Maybe you could rename the prop to something else like isSingleTheme or isThemeList, since that's generic enough for both the Design Picker (/setup/onboarding/designSetup) and the Theme Showcase (/themes).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. Testing
Projects
None yet
8 participants