diff --git a/packages/data-stores/src/add-ons/index.ts b/packages/data-stores/src/add-ons/index.ts index 55590f6551714c..c53300ef837507 100644 --- a/packages/data-stores/src/add-ons/index.ts +++ b/packages/data-stores/src/add-ons/index.ts @@ -3,6 +3,7 @@ export { default as useAddOns } from './hooks/use-add-ons'; export { default as useAddOnCheckoutLink } from './hooks/use-add-on-checkout-link'; export { default as useAddOnPurchaseStatus } from './hooks/use-add-on-purchase-status'; export { default as useStorageAddOns } from './hooks/use-storage-add-ons'; +export * from './constants'; /** Types */ export * from './types'; diff --git a/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts b/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts index acc4162a70e2a4..94c6dcb36fa85c 100644 --- a/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts +++ b/packages/data-stores/src/plans/hooks/use-pricing-meta-for-grid-plans.ts @@ -98,20 +98,16 @@ const usePricingMetaForGridPlans = ( { } else { planPrices = Object.fromEntries( planSlugs.map( ( planSlug ) => { - const availableForPurchase = planAvailabilityForPurchase[ planSlug ]; - const selectedStorageOption = selectedStorageOptions?.[ planSlug ]; - const selectedStorageAddOn = storageAddOns?.find( ( addOn ) => { - return selectedStorageOption && addOn?.featureSlugs?.includes( selectedStorageOption ); - } ); - const storageAddOnPrices = - selectedStorageAddOn?.purchased || selectedStorageAddOn?.exceedsSiteStorageLimits - ? null - : selectedStorageAddOn?.prices; - const storageAddOnPriceMonthly = storageAddOnPrices?.monthlyPrice || 0; - const storageAddOnPriceYearly = storageAddOnPrices?.yearlyPrice || 0; - const plan = plans.data?.[ planSlug ]; const sitePlan = sitePlans.data?.[ planSlug ]; + const selectedStorageOption = selectedStorageOptions?.[ planSlug ]; + const selectedStorageAddOn = selectedStorageOption + ? storageAddOns?.find( ( addOn ) => { + return addOn?.featureSlugs?.includes( selectedStorageOption ); + } ) + : null; + const storageAddOnPriceMonthly = selectedStorageAddOn?.prices?.monthlyPrice || 0; + const storageAddOnPriceYearly = selectedStorageAddOn?.prices?.yearlyPrice || 0; /** * 0. No plan or sitePlan (when selected site exists): planSlug is for a priceless plan. @@ -176,7 +172,7 @@ const usePricingMetaForGridPlans = ( { /** * 2. Original and Discounted prices for plan available for purchase. */ - if ( availableForPurchase ) { + if ( planAvailabilityForPurchase[ planSlug ] ) { const originalPrice = { monthly: getTotalPrice( plan.pricing.originalPrice.monthly, storageAddOnPriceMonthly ), full: getTotalPrice( plan.pricing.originalPrice.full, storageAddOnPriceYearly ), diff --git a/packages/plans-grid-next/src/components/actions.tsx b/packages/plans-grid-next/src/components/actions.tsx index 0940bc1b32f052..b604974b72a26a 100644 --- a/packages/plans-grid-next/src/components/actions.tsx +++ b/packages/plans-grid-next/src/components/actions.tsx @@ -142,10 +142,12 @@ const PlanFeatures2023GridActions = ( { const canPurchaseStorageAddOns = storageAddOnsForPlan?.some( ( storageAddOn ) => ! storageAddOn?.purchased && ! storageAddOn?.exceedsSiteStorageLimits ); + const storageAddOnCheckoutHref = storageAddOnsForPlan?.find( ( addOn ) => selectedStorageOptionForPlan && addOn?.featureSlugs?.includes( selectedStorageOptionForPlan ) )?.checkoutLink; + const nonDefaultStorageOptionSelected = defaultStorageOption !== selectedStorageOptionForPlan; let actionButton = ( diff --git a/packages/plans-grid-next/src/components/comparison-grid/index.tsx b/packages/plans-grid-next/src/components/comparison-grid/index.tsx index 0824bef1008349..4371689f516485 100644 --- a/packages/plans-grid-next/src/components/comparison-grid/index.tsx +++ b/packages/plans-grid-next/src/components/comparison-grid/index.tsx @@ -31,7 +31,6 @@ import filterUnusedFeaturesObject from '../../lib/filter-unused-features-object' import getPlanFeaturesObject from '../../lib/get-plan-features-object'; import { isStorageUpgradeableForPlan } from '../../lib/is-storage-upgradeable-for-plan'; import { sortPlans } from '../../lib/sort-plan-properties'; -import { getStorageStringFromFeature } from '../../util'; import PlanFeatures2023GridActions from '../actions'; import PlanFeatures2023GridHeaderPrice from '../header-price'; import PlanTypeSelector from '../plan-type-selector'; @@ -39,6 +38,7 @@ import { Plans2023Tooltip } from '../plans-2023-tooltip'; import PopularBadge from '../popular-badge'; import BillingTimeframe from '../shared/billing-timeframe'; import { StickyContainer } from '../sticky-container'; +import { PlanStorageLabel, useGetAvailableStorageOptions } from '../storage'; import StorageAddOnDropdown from '../storage-add-on-dropdown'; import type { GridPlan, @@ -299,25 +299,6 @@ const PlanSelector = styled.header` } `; -const StorageButton = styled.div` - background: #f2f2f2; - border-radius: 5px; - padding: 4px 0; - width: -moz-fit-content; - width: fit-content; - text-align: center; - font-size: 0.75rem; - font-weight: 400; - line-height: 20px; - color: var( --studio-gray-90 ); - min-width: 64px; - margin-top: 10px; - - ${ plansGridMediumLarge( css` - margin-top: 0; - ` ) } -`; - const FeatureFootnotes = styled.div` ol { margin: 2em 0 0 1em; @@ -584,6 +565,38 @@ const ComparisonGridFeatureGroupRowCell: React.FunctionComponent< { renderedGridPlans: visibleGridPlans, } ); + /** + * TODO: Consider centralising `canUpgradeStorageForPlan` behind `availableStorageOptions` + */ + const availableStorageOptions = useGetAvailableStorageOptions()( { + storageOptions: gridPlan.features.storageOptions, + } ); + /** + * The current plan is not marked as `availableForPurchase`, hence check on `current`. + */ + const canUpgradeStorageForPlan = + ( gridPlan.current || gridPlan.availableForPurchase ) && + isStorageUpgradeableForPlan( { + intervalType, + showUpgradeableStorage, + storageOptions: availableStorageOptions, + } ); + + const storageJSX = canUpgradeStorageForPlan ? ( + + ) : ( + gridPlan.features.storageOptions.map( ( storageOption ) => { + if ( ! storageOption?.isAddOn ) { + return ; + } + } ) + ); + if ( ! gridPlan ) { return null; } @@ -605,13 +618,6 @@ const ComparisonGridFeatureGroupRowCell: React.FunctionComponent< { ( feature ) => feature.getSlug() === featureSlug ) : false; - const storageOptions = gridPlan.features.storageOptions; - const defaultStorageOption = storageOptions.find( ( option ) => ! option.isAddOn ); - const canUpgradeStorageForPlan = isStorageUpgradeableForPlan( { - intervalType, - showUpgradeableStorage, - storageOptions, - } ); const cellClasses = classNames( 'plan-comparison-grid__feature-group-row-cell', @@ -638,18 +644,7 @@ const ComparisonGridFeatureGroupRowCell: React.FunctionComponent< { { isStorageFeature ? ( <> { translate( 'Storage' ) } - { canUpgradeStorageForPlan ? ( - - ) : ( - - { getStorageStringFromFeature( defaultStorageOption?.slug || '' ) } - - ) } + { storageJSX } ) : ( <> diff --git a/packages/plans-grid-next/src/components/features-grid/plan-storage-options.tsx b/packages/plans-grid-next/src/components/features-grid/plan-storage-options.tsx index 2a02a3b2601477..84f4c98680147b 100644 --- a/packages/plans-grid-next/src/components/features-grid/plan-storage-options.tsx +++ b/packages/plans-grid-next/src/components/features-grid/plan-storage-options.tsx @@ -5,8 +5,8 @@ import { } from '@automattic/calypso-products'; import { usePlansGridContext } from '../../grid-context'; import { isStorageUpgradeableForPlan } from '../../lib/is-storage-upgradeable-for-plan'; -import { getStorageStringFromFeature } from '../../util'; import { PlanFeaturesItem } from '../item'; +import { PlanStorageLabel, useGetAvailableStorageOptions } from '../storage'; import StorageAddOnDropdown from '../storage-add-on-dropdown'; type PlanStorageOptionsProps = { @@ -30,36 +30,43 @@ const PlanStorageOptions = ( { const { availableForPurchase, features: { storageOptions }, + current, } = gridPlansIndex[ planSlug ]; - const canUpgradeStorageForPlan = isStorageUpgradeableForPlan( { - intervalType, - showUpgradeableStorage, - storageOptions, - } ); - - const storageJSX = - canUpgradeStorageForPlan && availableForPurchase ? ( - - ) : ( - storageOptions.map( ( storageOption ) => { - if ( ! storageOption?.isAddOn ) { - return ( -
- { getStorageStringFromFeature( storageOption?.slug ) } -
- ); - } - } ) - ); + const getAvailableStorageOptions = useGetAvailableStorageOptions(); if ( ! options?.isTableCell && isWpcomEnterpriseGridPlan( planSlug ) ) { return null; } + /** + * TODO: Consider centralising `canUpgradeStorageForPlan` behind `availableStorageOptions` + */ + const availableStorageOptions = getAvailableStorageOptions( { storageOptions } ); + /** + * The current plan is not marked as `availableForPurchase`, hence check on `current`. + */ + const canUpgradeStorageForPlan = + ( current || availableForPurchase ) && + isStorageUpgradeableForPlan( { + intervalType, + showUpgradeableStorage, + storageOptions: availableStorageOptions, + } ); + + const storageJSX = canUpgradeStorageForPlan ? ( + + ) : ( + storageOptions.map( ( storageOption ) => { + if ( ! storageOption?.isAddOn ) { + return ; + } + } ) + ); + return (
{ storageJSX } diff --git a/packages/plans-grid-next/src/components/storage-add-on-dropdown.tsx b/packages/plans-grid-next/src/components/storage-add-on-dropdown.tsx index 1feb74a594594c..9853b5dfacb8ed 100644 --- a/packages/plans-grid-next/src/components/storage-add-on-dropdown.tsx +++ b/packages/plans-grid-next/src/components/storage-add-on-dropdown.tsx @@ -6,8 +6,8 @@ import { useTranslate } from 'i18n-calypso'; import { usePlansGridContext } from '../grid-context'; import useDefaultStorageOption from '../hooks/data-store/use-default-storage-option'; import useIsLargeCurrency from '../hooks/use-is-large-currency'; -import { getStorageStringFromFeature } from '../util'; import DropdownOption from './dropdown-option'; +import { useStorageStringFromFeature } from './storage'; import type { PlanSlug, StorageOption, WPComStorageAddOnSlug } from '@automattic/calypso-products'; import type { AddOnMeta } from '@automattic/data-stores'; @@ -19,8 +19,9 @@ type StorageAddOnDropdownProps = { }; type StorageAddOnOptionProps = { - title?: string; + planSlug: PlanSlug; price?: string; + storageFeature: string; isLargeCurrency?: boolean; priceOnSeparateLine?: boolean; }; @@ -35,16 +36,15 @@ const getStorageOptionPrice = ( }; const StorageAddOnOption = ( { - title, + planSlug, price, + storageFeature, isLargeCurrency = false, priceOnSeparateLine, }: StorageAddOnOptionProps ) => { const translate = useTranslate(); - - if ( ! title ) { - return null; - } + const { siteId } = usePlansGridContext(); + const title = useStorageStringFromFeature( { storageFeature, siteId, planSlug } ) ?? ''; return ( <> @@ -114,28 +114,30 @@ export const StorageAddOnDropdown = ( { }, [] ); const selectControlOptions = storageOptions.map( ( storageOption ) => { - const title = getStorageStringFromFeature( storageOption.slug ) || ''; - const price = getStorageOptionPrice( storageAddOnsForPlan, storageOption.slug ); return { key: storageOption.slug, - name: , + name: ( + + ), }; } ); const selectedOptionKey = selectedStorageOptionForPlan ? selectedStorageOptionForPlan : defaultStorageOption; - const selectedOptionPrice = - selectedOptionKey && getStorageOptionPrice( storageAddOnsForPlan, selectedOptionKey ); - const selectedOptionTitle = - ( selectedOptionKey && getStorageStringFromFeature( selectedOptionKey ) ) || ''; + const selectedOptionPrice = getStorageOptionPrice( storageAddOnsForPlan, selectedOptionKey ); const selectedOption = { key: selectedOptionKey, name: ( diff --git a/packages/plans-grid-next/src/components/storage/components/plan-storage-label.tsx b/packages/plans-grid-next/src/components/storage/components/plan-storage-label.tsx new file mode 100644 index 00000000000000..599e280af135dc --- /dev/null +++ b/packages/plans-grid-next/src/components/storage/components/plan-storage-label.tsx @@ -0,0 +1,72 @@ +import { + PLAN_BUSINESS, + PLAN_ECOMMERCE, + PlanSlug, + StorageOption, +} from '@automattic/calypso-products'; +import { AddOns } from '@automattic/data-stores'; +import { formatCurrency } from '@automattic/format-currency'; +import classNames from 'classnames'; +import { useTranslate } from 'i18n-calypso'; +import { usePlansGridContext } from '../../../grid-context'; +import useIsLargeCurrency from '../../../hooks/use-is-large-currency'; +import useStorageStringFromFeature from '../hooks/use-storage-string-from-feature'; + +interface Props { + storageOption: StorageOption; + planSlug: PlanSlug; +} + +const ELIGIBLE_PLANS_FOR_STORAGE_UPGRADE = [ PLAN_BUSINESS, PLAN_ECOMMERCE ]; + +const PlanStorageLabel = ( { storageOption, planSlug }: Props ) => { + const translate = useTranslate(); + const { siteId, gridPlansIndex } = usePlansGridContext(); + const currencyCode = gridPlansIndex[ planSlug ].pricing.currencyCode; + const storageStringFromFeature = useStorageStringFromFeature( { + siteId, + storageFeature: storageOption.slug, + planSlug, + } ); + const storageAddOns = AddOns.useStorageAddOns( { siteId } ); + const storageAddOnsPurchased = storageAddOns.filter( ( addOn ) => addOn?.purchased ); + const monthlyAddedCost = storageAddOnsPurchased + ? Object.values( storageAddOnsPurchased ).reduce( ( total, addOn ) => { + return total + ( addOn?.prices?.monthlyPrice ?? 0 ); + }, 0 ) + : 0; + const formattedMonthlyAddedCost = + monthlyAddedCost && + currencyCode && + formatCurrency( monthlyAddedCost, currencyCode, { isSmallestUnit: true } ); + const isLargeCurrency = useIsLargeCurrency( { + prices: [ monthlyAddedCost ], + isAddOn: true, + currencyCode: currencyCode ?? 'USD', + } ); + + const containerClasses = classNames( 'plans-grid-next-plan-storage-label__container', { + 'is-row': ! isLargeCurrency, + } ); + + const volumeJSX = ( +
+ { storageStringFromFeature } +
+ ); + + return formattedMonthlyAddedCost && ELIGIBLE_PLANS_FOR_STORAGE_UPGRADE.includes( planSlug ) ? ( +
+ { volumeJSX } +
+ { translate( '+ %(formattedMonthlyAddedCost)s/month', { + args: { formattedMonthlyAddedCost }, + } ) } +
+
+ ) : ( + volumeJSX + ); +}; + +export default PlanStorageLabel; diff --git a/packages/plans-grid-next/src/components/storage/hooks/use-get-available-storage-options.ts b/packages/plans-grid-next/src/components/storage/hooks/use-get-available-storage-options.ts new file mode 100644 index 00000000000000..a5c7961dd87682 --- /dev/null +++ b/packages/plans-grid-next/src/components/storage/hooks/use-get-available-storage-options.ts @@ -0,0 +1,45 @@ +import { StorageOption } from '@automattic/calypso-products'; +import { AddOns, Site } from '@automattic/data-stores'; +import { useCallback } from '@wordpress/element'; +import { usePlansGridContext } from '../../../grid-context'; + +interface CallbackProps { + storageOptions: StorageOption[]; +} + +/** + * Ensures that storage options are filtered based on: + * - the available space upgrade on the Site, + * so never render something that would exceed that limit (hence fail during checkout) + * - storage option being allowed for purchase only once (cannot repurchase same add-on on any site) + */ +const useGetAvailableStorageOptions = () => { + const { siteId } = usePlansGridContext(); + const siteMediaStorage = Site.useSiteMediaStorage( { siteIdOrSlug: siteId } ); + const currentMaxStorage = siteMediaStorage.data?.maxStorageBytes + ? siteMediaStorage.data.maxStorageBytes / Math.pow( 1024, 3 ) + : 0; + const availableStorageUpgrade = AddOns.STORAGE_LIMIT - currentMaxStorage; + const storageAddOns = AddOns.useStorageAddOns( { siteId } ); + + return useCallback( + ( { storageOptions }: CallbackProps ) => { + return storageOptions.filter( ( storageOption ) => { + const storageAddOn = storageAddOns.find( + ( addOn ) => + ! addOn?.purchased && + addOn?.featureSlugs?.includes( storageOption?.slug ) && + ! addOn.exceedsSiteStorageLimits + ); + + // the following may not be necessary if `exceedsSiteStorageLimits` suffices + return storageAddOn + ? ( storageAddOn?.quantity ?? 0 ) <= availableStorageUpgrade + : ! storageOption.isAddOn; + } ); + }, + [ availableStorageUpgrade, storageAddOns ] + ); +}; + +export default useGetAvailableStorageOptions; diff --git a/packages/plans-grid-next/src/components/storage/hooks/use-storage-string-from-feature.ts b/packages/plans-grid-next/src/components/storage/hooks/use-storage-string-from-feature.ts new file mode 100644 index 00000000000000..f8c92a81ace5b2 --- /dev/null +++ b/packages/plans-grid-next/src/components/storage/hooks/use-storage-string-from-feature.ts @@ -0,0 +1,91 @@ +import { + FEATURE_1GB_STORAGE, + FEATURE_6GB_STORAGE, + FEATURE_13GB_STORAGE, + FEATURE_50GB_STORAGE, + FEATURE_200GB_STORAGE, + FEATURE_50GB_STORAGE_ADD_ON, + FEATURE_100GB_STORAGE_ADD_ON, + FEATURE_P2_3GB_STORAGE, + FEATURE_P2_13GB_STORAGE, + PRODUCT_1GB_SPACE, + PlanSlug, + PLAN_BUSINESS, + PLAN_ECOMMERCE, +} from '@automattic/calypso-products'; +import { Purchases } from '@automattic/data-stores'; +import { useTranslate } from 'i18n-calypso'; + +const ELIGIBLE_PLANS_FOR_STORAGE_UPGRADE = [ PLAN_BUSINESS, PLAN_ECOMMERCE ]; + +const useStorageStringFromFeature = ( { + storageFeature, + siteId, + planSlug, +}: { + storageFeature: string; + siteId?: null | number | string; + planSlug: PlanSlug; +} ) => { + const translate = useTranslate(); + const spaceUpgradesPurchased = Purchases.useSitePurchasesByProductSlug( { + siteId, + productSlug: PRODUCT_1GB_SPACE, + } ); + const purchasedQuantityTotal = spaceUpgradesPurchased + ? Object.values( spaceUpgradesPurchased ).reduce( ( total, current ) => { + return total + current.purchaseRenewalQuantity; + }, 0 ) + : 0; + + switch ( storageFeature ) { + case FEATURE_1GB_STORAGE: + return translate( '1 GB' ); + case FEATURE_6GB_STORAGE: + return translate( '6 GB' ); + case FEATURE_13GB_STORAGE: + return translate( '13 GB' ); + case FEATURE_50GB_STORAGE: + /** + * TODO: Don't do this here. Diverge and show the version with the green pricing next + */ + return translate( '%(quantity)d GB', { + args: { + quantity: ELIGIBLE_PLANS_FOR_STORAGE_UPGRADE.includes( planSlug ) + ? purchasedQuantityTotal + 50 + : 50, + }, + } ); + case FEATURE_P2_3GB_STORAGE: + return translate( '3 GB' ); + case FEATURE_P2_13GB_STORAGE: + return translate( '13 GB' ); + // TODO: Remove when upgradeable storage is released in plans 2023 + case FEATURE_200GB_STORAGE: + return translate( '200 GB' ); + case FEATURE_50GB_STORAGE_ADD_ON: + /** + * Displayed string is: purchased storage + default 50GB storage + Add-On + * TODO: the default 50GB should be coming from plan context, not hardcoded here + */ + return translate( '%(quantity)d GB', { + args: { + quantity: purchasedQuantityTotal + 50 + 50, + }, + } ); + case FEATURE_100GB_STORAGE_ADD_ON: + /** + * Displayed string is: purchased storage + default 50GB storage + Add-On + * TODO: the default 50GB should be coming from plan context, not hardcoded here + */ + return translate( '%(quantity)d GB', { + args: { + quantity: purchasedQuantityTotal + 50 + 100, + }, + } ); + default: + return null; + } +}; + +export default useStorageStringFromFeature; diff --git a/packages/plans-grid-next/src/components/storage/index.ts b/packages/plans-grid-next/src/components/storage/index.ts new file mode 100644 index 00000000000000..5e7513decdfc3f --- /dev/null +++ b/packages/plans-grid-next/src/components/storage/index.ts @@ -0,0 +1,11 @@ +/** + * Hooks + */ +export { default as useStorageStringFromFeature } from './hooks/use-storage-string-from-feature'; +export { default as useGetAvailableStorageOptions } from './hooks/use-get-available-storage-options'; + +/** + * Components + */ +// Consider exporting a single generalised `PlanStorageOptions` component that can be used in both Comparison and Features grid. +export { default as PlanStorageLabel } from './components/plan-storage-label'; diff --git a/packages/plans-grid-next/src/lib/is-storage-upgradeable-for-plan.ts b/packages/plans-grid-next/src/lib/is-storage-upgradeable-for-plan.ts index e631e65df46999..6a10e158129374 100644 --- a/packages/plans-grid-next/src/lib/is-storage-upgradeable-for-plan.ts +++ b/packages/plans-grid-next/src/lib/is-storage-upgradeable-for-plan.ts @@ -15,4 +15,7 @@ export const isStorageUpgradeableForPlan = ( { intervalType: string; showUpgradeableStorage: boolean; storageOptions: StorageOption[]; -} ) => storageOptions.length > 1 && intervalType === 'yearly' && showUpgradeableStorage; +} ) => + storageOptions.find( ( option ) => option.isAddOn ) && + intervalType === 'yearly' && + showUpgradeableStorage; diff --git a/packages/plans-grid-next/src/style.scss b/packages/plans-grid-next/src/style.scss index ec6c57af423699..be7238f75bce7d 100644 --- a/packages/plans-grid-next/src/style.scss +++ b/packages/plans-grid-next/src/style.scss @@ -326,12 +326,6 @@ $mobile-card-max-width: 440px; padding-bottom: 23px; } - &.plan-features-2023-grid__storage { - padding-top: 0; - padding-bottom: 32px; - width: 205px; - } - .plan-features-2023-grid__header-title { margin-top: 24px; } @@ -462,19 +456,6 @@ $mobile-card-max-width: 440px; } } -.storage-add-on-dropdown__offset-price-container { - width: 100%; - margin-top: 8px; - text-align: left; - - .storage-add-on-dropdown__offset-price { - color: var(--studio-green-50); - - font-size: 0.75rem; - font-weight: 500; - } -} - .plan-features-2023-grid__content { .plan-features-2023-grid__table-bottom { margin-top: 54px; @@ -628,19 +609,11 @@ $mobile-card-max-width: 440px; padding: 24px 0 6px 20px; } - .plan-features-2023-grid__storage { - .plan-features-2023-grid__storage-buttons { - background: #f2f2f2; - /* stylelint-disable-next-line */ - border-radius: 5px; - padding: 4px 0; - width: fit-content; - text-align: center; - font-size: $font-body-extra-small; - font-weight: 400; - line-height: 20px; - color: var(--studio-gray-90); - min-width: 64px; + &.plan-features-2023-grid__storage { + padding: 24px 20px 38px 20px; + + .plan-features-2023-grid__storage-title { + margin-bottom: 10px; } } @@ -1056,3 +1029,75 @@ $mobile-card-max-width: 440px; } } } + +/** + * Storage Add-On Dropdown parts + */ + +.plans-grid-next-plan-storage-label__container { + display: flex; + gap: 5px; + flex-direction: column; + align-items: baseline; + + &.is-row { + flex-direction: row; + } + + /** + * Comparison grid overrides + * - always render as column/wrapped + */ + .plans-grid-next-comparison-grid & { + flex-direction: column; + align-items: center; + } +} + +.plans-grid-next-plan-storage-label__offset-price { + color: var(--studio-green-50); + font-size: $font-body-extra-small; + font-weight: 500; +} + +.storage-add-on-dropdown__offset-price-container { + width: 100%; + margin-top: 8px; + text-align: left; + + .storage-add-on-dropdown__offset-price { + color: var(--studio-green-50); + font-size: $font-body-extra-small; + font-weight: 500; + } +} + +.plan-features-2023-grid__storage-buttons { + background: #f2f2f2; + color: var(--studio-gray-90); + /* stylelint-disable-next-line */ + border-radius: 5px; + padding: 4px 0; + text-align: center; + font-size: $font-body-extra-small; + font-weight: 400; + line-height: 20px; + width: fit-content; + min-width: 64px; + + .plans-grid-next-comparison-grid & { + margin-top: 10px; + + @include plans-grid-medium-large { + margin-top: 0; + } + } +} + +.plan-features-2023-grid__storage { + .plan-features-2023-grid__plan-spotlight & { + padding-top: 0; + padding-bottom: 32px; + max-width: $table-cell-max-width; + } +} diff --git a/packages/plans-grid-next/src/util.ts b/packages/plans-grid-next/src/util.ts deleted file mode 100644 index edd2887be98837..00000000000000 --- a/packages/plans-grid-next/src/util.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - FEATURE_1GB_STORAGE, - FEATURE_6GB_STORAGE, - FEATURE_13GB_STORAGE, - FEATURE_50GB_STORAGE, - FEATURE_200GB_STORAGE, - FEATURE_50GB_STORAGE_ADD_ON, - FEATURE_100GB_STORAGE_ADD_ON, - FEATURE_P2_3GB_STORAGE, - FEATURE_P2_13GB_STORAGE, -} from '@automattic/calypso-products'; -import { translate } from 'i18n-calypso'; - -export const getStorageStringFromFeature = ( storageFeature: string ) => { - switch ( storageFeature ) { - case FEATURE_1GB_STORAGE: - return translate( '1 GB' ); - case FEATURE_6GB_STORAGE: - return translate( '6 GB' ); - case FEATURE_13GB_STORAGE: - return translate( '13 GB' ); - case FEATURE_50GB_STORAGE: - return translate( '50 GB' ); - case FEATURE_P2_3GB_STORAGE: - return translate( '3 GB' ); - case FEATURE_P2_13GB_STORAGE: - return translate( '13 GB' ); - // TODO: Remove when upgradeable storage is released in plans 2023 - case FEATURE_200GB_STORAGE: - return translate( '200 GB' ); - // Displayed string is the Add On + default 50GB storage - case FEATURE_50GB_STORAGE_ADD_ON: - return translate( '100 GB' ); - case FEATURE_100GB_STORAGE_ADD_ON: - return translate( '150 GB' ); - default: - return null; - } -};