diff --git a/services/web/app/views/subscriptions/plans/light-redesign/_mixins.pug b/services/web/app/views/subscriptions/plans/light-redesign/_mixins.pug index 815c01c947..1d6cb29b1c 100644 --- a/services/web/app/views/subscriptions/plans/light-redesign/_mixins.pug +++ b/services/web/app/views/subscriptions/plans/light-redesign/_mixins.pug @@ -26,6 +26,27 @@ mixin currency_and_payment_methods() i.fa.fa-cc-paypal.fa-2x(aria-hidden="true")   span.sr-only #{translate('payment_method_accepted', { paymentMethod: 'Paypal' })} +mixin plans_cta(tableHeadKey, highlighted, eventTrackingKey, additionalEventSegmentation, period) + case tableHeadKey + when 'individual_free' + +btn_buy_individual_free() + when 'individual_collaborator' + +btn_buy_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period) + when 'individual_professional' + +btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period) + when 'group_collaborator' + +btn_buy_group_collaborator(highlighted, eventTrackingKey) + +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_collaborator') + when 'group_professional' + +btn_buy_group_professional(highlighted, eventTrackingKey) + +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_professional') + when 'group_organization' + +btn_buy_group_organization(highlighted, eventTrackingKey) + small.plans-table-th-content-additional-link.invisible(aria-hidden="true") + when 'student_free' + +btn_buy_student_free(highlighted) + when 'student_student' + +btn_buy_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period) mixin plans_table(period, config) - var maxColumn = config.maxColumn || 4 @@ -42,50 +63,116 @@ mixin plans_table(period, config) - var additionalEventSegmentation = config.additionalEventSegmentation || {} - var thClass = highlighted ? 'plans-table-green-highlighted' : '' - case tableHeadKey - when 'individual_free' - - var ariaLabel = translate("free") - when 'individual_collaborator' - - var ariaLabel = translate("standard") - when 'individual_professional' - - var ariaLabel = translate("professional") - when 'group_collaborator' - - var ariaLabel = translate("group_standard") - when 'group_professional' - - var ariaLabel = translate("group_professional") - when 'group_organization' - - var ariaLabel = translate("organization") - when 'student_free' - - var ariaLabel = translate("free") - when 'student_student' - - var ariaLabel = translate("student") - default - - var ariaLabel = undefined th( - aria-label=ariaLabel class=thClass scope="col" ) .plans-table-th if (highlighted) p.plans-table-green-highlighted-text #{translate(config.highlightedColumn.text[period]).toUpperCase()} + .plans-table-th-content + if tableHeadKey + case tableHeadKey + when 'individual_free' + | #{translate("free")} + when 'individual_collaborator' + | #{translate("standard")} + when 'individual_professional' + | #{translate("professional")} + when 'group_collaborator' + | #{translate("group_standard")} + when 'group_professional' + | #{translate("group_professional")} + when 'group_organization' + | #{translate("organization")} + when 'student_free' + | #{translate("free")} + when 'student_student' + | #{translate("student")} + + tr(class=`plans-table-price-row plans-table-cols-${tableHeadKeys.length}`) + td + - for (const [tableHeadKey] of Object.entries(config.tableHead)) + - var highlighted = highlightedColKey === tableHeadKey + - var eventTrackingKey = config.eventTrackingKey + - var additionalEventSegmentation = config.additionalEventSegmentation || {} + - var tdClass = highlighted ? 'plans-table-green-highlighted' : '' + + td(class=tdClass) + .plans-table-cell case tableHeadKey when 'individual_free' - +table_head_individual_free(highlighted, period) + +table_head_price('free', period) when 'individual_collaborator' - +table_head_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period) + +table_head_price('collaborator', period) when 'individual_professional' - +table_head_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period) + +table_head_price('professional', period) when 'group_collaborator' - +table_head_group_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation) + +table_price_group_collaborator() when 'group_professional' - +table_head_group_professional(highlighted, eventTrackingKey, additionalEventSegmentation) + +table_price_group_professional() when 'group_organization' - +table_head_group_organization(highlighted, eventTrackingKey, additionalEventSegmentation) + .plans-table-comments-icon + i.fa.fa-comments-o when 'student_free' - +table_head_student_free(highlighted, period) + +table_head_price('free', period) when 'student_student' - +table_head_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period, tableHeadOptions.showExtraContent) + +table_head_price('student', period) + + tr(class=`plans-table-cta-mobile plans-table-cols-${tableHeadKeys.length}`) + td + - for (const [tableHeadKey] of Object.entries(config.tableHead)) + - var highlighted = highlightedColKey === tableHeadKey + - var eventTrackingKey = config.eventTrackingKey + - var additionalEventSegmentation = config.additionalEventSegmentation || {} + - var tdClass = highlighted ? 'plans-table-green-highlighted' : '' + + td(class=tdClass) + .plans-table-cell + .plans-table-btn-buy-container-mobile + +plans_cta(tableHeadKey, highlighted, eventTrackingKey, additionalEventSegmentation, period) + + tr(class=`plans-table-short-feature-list plans-table-cols-${tableHeadKeys.length}`) + td + - for (const [tableHeadKey, tableHeadOptions] of Object.entries(config.tableHead)) + - var highlighted = highlightedColKey === tableHeadKey + - var eventTrackingKey = config.eventTrackingKey + - var additionalEventSegmentation = config.additionalEventSegmentation || {} + - var tdClass = highlighted ? 'plans-table-green-highlighted' : '' + + td(class=tdClass) + .plans-table-cell + div + case tableHeadKey + when 'individual_free' + +table_short_feature_list_free() + when 'individual_collaborator' + +table_short_feature_list_collaborator() + when 'individual_professional' + +table_short_feature_list_professional() + when 'group_collaborator' + +table_short_feature_list_group_collaborator() + when 'group_professional' + +table_short_feature_list_group_professional() + when 'group_organization' + +table_short_feature_list_group_organization(additionalEventSegmentation) + when 'student_free' + +table_short_feature_list_free() + when 'student_student' + +table_short_feature_list_student_student(tableHeadOptions.showExtraContent) + + tr(class=`plans-table-cta-desktop plans-table-cols-${tableHeadKeys.length}`) + td + - for (const [tableHeadKey] of Object.entries(config.tableHead)) + - var highlighted = highlightedColKey === tableHeadKey + - var eventTrackingKey = config.eventTrackingKey + - var additionalEventSegmentation = config.additionalEventSegmentation || {} + - var tdClass = highlighted ? 'plans-table-green-highlighted' : '' + + td(class=tdClass) + .plans-table-cell + .plans-table-btn-buy-container-desktop + +plans_cta(tableHeadKey, highlighted, eventTrackingKey, additionalEventSegmentation, period) for featuresPerSection in config.features - var dividerColspan = Object.values(config.tableHead).length + 1 @@ -115,7 +202,7 @@ mixin plans_table(period, config) span.sr-only #{translate(featuresPerSection.dividerInfo)} for feature, featureIndex in featuresPerSection.items tr( - class=`plans-table-cols-${tableHeadKeys.length}` + class=`plans-table-feature-row plans-table-cols-${tableHeadKeys.length}` ) th( event-tracking="plans-page-table" @@ -123,6 +210,7 @@ mixin plans_table(period, config) event-tracking-ga="subscription-funnel" event-tracking-label=`${feature.feature}` scope="row" + class=`${featureIndex === 0 ? 'plans-table-first-feature-header' : ''}` ) .plans-table-feature-name if feature.info @@ -170,16 +258,6 @@ mixin table_short_feature_list_free() ul.plans-table-th-content-benefit li #{translate("one_collaborator")} -mixin table_head_individual_free(highlighted, period) - .plans-table-th-content - p.plans-table-th-content-title #{translate("free")} - +table_head_price('free', period) - .plans-table-btn-buy-container-mobile - +btn_buy_individual_free() - +table_short_feature_list_free() - .plans-table-btn-buy-container-desktop - +btn_buy_individual_free() - //- individual plan mixins mixin table_short_feature_list_collaborator() @@ -187,16 +265,6 @@ mixin table_short_feature_list_collaborator() li !{translate("x_collaborators_per_project", {collaboratorsCount: '10'})} li #{translate("all_premium_features")} -mixin table_head_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period) - .plans-table-th-content - p.plans-table-th-content-title #{translate("standard")} - +table_head_price('collaborator', period) - .plans-table-btn-buy-container-mobile - +btn_buy_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period) - +table_short_feature_list_collaborator() - .plans-table-btn-buy-container-desktop - +btn_buy_individual_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation, period) - //- professional plan mixins mixin table_short_feature_list_professional() @@ -204,16 +272,6 @@ mixin table_short_feature_list_professional() li !{translate("unlimited_collabs_rt",{},["b"])} li #{translate("all_premium_features")} -mixin table_head_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period) - .plans-table-th-content - p.plans-table-th-content-title #{translate("professional")} - +table_head_price('professional', period) - .plans-table-btn-buy-container-mobile - +btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period) - +table_short_feature_list_professional() - .plans-table-btn-buy-container-desktop - +btn_buy_individual_professional(highlighted, eventTrackingKey, additionalEventSegmentation, period) - //- group_collaborator plan mixins mixin table_short_feature_list_group_collaborator() @@ -223,26 +281,14 @@ mixin table_short_feature_list_group_collaborator() +table_head_group_total_per_year('collaborator') mixin table_price_group_collaborator() - .plans-v2-table-price-container - strike.plans-v2-table-price-before-discount + .plans-table-price-container + s +gen_localized_price_for_plan_view('collaborator', 'annual') p.plans-v2-table-price span(data-ol-plans-v2-group-price-per-user='collaborator') #{initialLocalizedGroupPrice.pricePerUser.collaborator} p.plans-v2-table-price-period-label | #{translate('per_user_year')} -mixin table_head_group_collaborator(highlighted, eventTrackingKey, additionalEventSegmentation) - .plans-table-th-content - p.plans-table-th-content-title #{translate("group_standard")} - +table_price_group_collaborator() - .plans-table-btn-buy-container-mobile - +btn_buy_group_collaborator(highlighted, eventTrackingKey) - +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_collaborator') - +table_short_feature_list_group_collaborator() - .plans-table-btn-buy-container-desktop - +btn_buy_group_collaborator(highlighted, eventTrackingKey) - +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_collaborator') - //- group_professional plan mixins mixin table_short_feature_list_group_professional() @@ -252,26 +298,14 @@ mixin table_short_feature_list_group_professional() +table_head_group_total_per_year('professional') mixin table_price_group_professional() - .plans-v2-table-price-container - strike.plans-v2-table-price-before-discount + .plans-table-price-container + s +gen_localized_price_for_plan_view('professional', 'annual') p.plans-v2-table-price span(data-ol-plans-v2-group-price-per-user='professional') #{initialLocalizedGroupPrice.pricePerUser.professional} p.plans-v2-table-price-period-label | #{translate('per_user_year')} -mixin table_head_group_professional(highlighted, eventTrackingKey, additionalEventSegmentation) - .plans-table-th-content - p.plans-table-th-content-title #{translate("group_professional")} - +table_price_group_professional() - .plans-table-btn-buy-container-mobile - +btn_buy_group_professional(highlighted, eventTrackingKey) - +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_professional') - +table_short_feature_list_group_professional() - .plans-table-btn-buy-container-desktop - +btn_buy_group_professional(highlighted, eventTrackingKey) - +additional_link_group(eventTrackingKey, additionalEventSegmentation, 'group_professional') - //- group mixins mixin table_head_group_total_per_year(groupPlan) @@ -299,20 +333,6 @@ mixin table_short_feature_list_group_organization(additionalEventSegmentation) event-segmentation=segmentation ) #{translate("also_available_as_on_premises")} -mixin table_head_group_organization(highlighted, eventTrackingKey, additionalEventSegmentation) - .plans-table-th-content - p.plans-table-th-content-title #{translate("organization")} - .plans-table-comments-icon - i.fa.fa-comments-o - .plans-table-btn-buy-container-mobile - +btn_buy_group_organization(highlighted, eventTrackingKey) - small.plans-table-th-content-additional-link.invisible(aria-hidden="true") - +table_short_feature_list_group_organization(additionalEventSegmentation) - .plans-table-btn-buy-container-desktop - +btn_buy_group_organization(highlighted, eventTrackingKey) - small.plans-table-th-content-additional-link.invisible(aria-hidden="true") - - mixin group_plans_license_picker() form.plans-license-picker-form(data-ol-plans-v2-license-picker-form) .plans-v2-license-picker-select-container @@ -364,18 +384,6 @@ mixin group_plans_license_picker() span ) span.sr-only #{translate("apply_educational_discount_info")} -//- student free plan mixins - -mixin table_head_student_free(highlighted, period) - div.plans-table-th-content - p.plans-table-th-content-title #{translate("free")} - +table_head_price('free', period) - .plans-table-btn-buy-container-mobile - +btn_buy_student_free(highlighted) - +table_short_feature_list_free() - .plans-table-btn-buy-container-desktop - +btn_buy_student_free(highlighted) - //- student plan mixins mixin table_short_feature_list_student_student(showExtraContent) @@ -386,23 +394,12 @@ mixin table_short_feature_list_student_student(showExtraContent) li b !{translate("for_students_only")} -mixin table_head_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period, showExtraContent) - div.plans-table-th-content - p.plans-table-th-content-title #{translate("student")} - +table_head_price('student', period) - .plans-table-btn-buy-container-mobile - +btn_buy_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period) - +table_short_feature_list_student_student(showExtraContent) - - .plans-table-btn-buy-container-desktop - +btn_buy_student_student(highlighted, eventTrackingKey, additionalEventSegmentation, period) - //- all plans mixins mixin table_head_price(plan, period) - div.plans-v2-table-price-container + div.plans-table-price-container if plan !== 'free' && period === 'annual' - strike.plans-v2-table-price-before-discount + s +gen_localized_price_for_plan_view(plan, 'monthlyTimesTwelve') p.plans-v2-table-price +gen_localized_price_for_plan_view(plan, period) diff --git a/services/web/frontend/stylesheets/app/plans/plans-light-touch-redesign.less b/services/web/frontend/stylesheets/app/plans/plans-light-touch-redesign.less index a9e19c1159..a98af55010 100644 --- a/services/web/frontend/stylesheets/app/plans/plans-light-touch-redesign.less +++ b/services/web/frontend/stylesheets/app/plans/plans-light-touch-redesign.less @@ -442,10 +442,6 @@ @media (max-width: @screen-xs-max) { margin-top: 60px + @plans-highlighted-text-height-desktop; - - th .plans-table-th-content { - min-height: 280px; - } } } @@ -464,24 +460,6 @@ .plans-table-group { margin-top: 26px + @plans-highlighted-text-height-desktop; - - p.plans-table-th-content-title { - // Reduce font size of table heading for screen size >= @screen-lg (1200px) from 20px to 19px - // In the English version of overleaf, 20px is enough for the text to not be wrapped to the next line, the longest text is the 2nd column of group tab: "Group Professional". - // In the English version, "Group Professional" won't be wrapped to two separate lines with 20px font size for big screen. - // In other languages, for example, German (subdomain `de`), 20px is too big so the text is wrapped and breaks the UI. 19px is enough to fit the text on one line on the German site. - // This font-size reduction is a case-to-case basis since we don't have any way to know the max length of every language unless we've translated them all. - // There's probably a smarter way to do it, but probably also more complex. This change in font should be acceptable and we can revisit it every time there's a longer text. - font-size: 19px; - - @media (max-width: @screen-md-max) { - font-size: @font-size-base; - } - - @media (max-width: @screen-xs-max) { - font-size: @font-size-small; - } - } } .plans-table { @@ -545,6 +523,35 @@ } } + .plans-table-cta-desktop, + .plans-table-cta-mobile, + .plans-table-short-feature-list, + .plans-table-price-row { + td > div { + border-top: 0; + } + } + + th[scope='col'] > div { + padding: var(--spacing-06) var(--spacing-08); + } + th[scope='row'] > div { + padding: var(--spacing-05) var(--spacing-08) var(--spacing-05) + var(--spacing-05); + } + td > div > div { + // apply spacing to inner div to not interfere with border + padding: var(--spacing-05) var(--spacing-08); + + @media (max-width: @screen-xs-max) { + padding: var(--spacing-05); + } + } + tr.plans-table-divider > td > div { + // td style above not applied since there is only 1 level of div within divider cells + padding: var(--spacing-05) var(--spacing-08); + } + // We want these `div` inside `th` and `td` to have a 100% height since // white backgrounds are defined here: // 1. `td > div.plans-table-cell` @@ -622,12 +629,11 @@ } th[scope='col'] { - font-family: @headings-font-family; - font-size: @font-size-h2; - font-weight: @headings-font-weight; - line-height: @headings-line-height; + font-family: 'Noto Sans', sans-serif; + font-size: var(--font-size-05); + font-weight: 600; + line-height: var(--line-height-04); vertical-align: top; - padding: 0; position: relative; &.plans-table-green-highlighted { @@ -648,15 +654,12 @@ position: relative; } - // css hack for table border-radius on the first feature name - &:nth-child(2) { - th[scope='row']:first-child { - .plans-table-feature-name { - border-top-left-radius: @plans-table-border-radius; + .plans-table-first-feature-header { + .plans-table-feature-name { + border-top-left-radius: @plans-table-border-radius; - @media (max-width: @screen-xs-max) { - border-top-left-radius: 0; - } + @media (max-width: @screen-xs-max) { + border-top-left-radius: 0; } } } @@ -673,7 +676,6 @@ // direct child selector to NOT affect the generated tooltip td > div { text-align: center; - padding: 6px; .plans-table-divider-label { margin-bottom: 0; @@ -702,8 +704,6 @@ td > div { background-color: var(--neutral-20); border: 0; - padding: 15px 5px; - i { display: none; } @@ -758,7 +758,7 @@ @media (min-width: @screen-sm-min) { // highlight rows on hover - tr:not(.plans-table-divider):not(:first-child):hover { + .plans-table-feature-row:hover { .plans-table-feature-name, .plans-table-cell { background-color: @table-hover-bg; @@ -802,9 +802,15 @@ font-size: 12px; } - // hide the first column header - tr:first-child th:first-child { - display: none; + // hide the first cell (which has no content) + tr:first-child, + .plans-table-price-row, + .plans-table-cta-mobile, + .plans-table-short-feature-list { + th:first-child, + td:first-child { + display: none; + } } // for mobile, we need to show the feature name (the first td) as its own row @@ -840,7 +846,6 @@ @media (max-width: @screen-xs-max) { .plans-table-cell-content { - padding: 6px; min-height: @plans-table-td-mobile-min-height; } } @@ -852,13 +857,7 @@ .plans-table-th-content { display: flex; flex-direction: column; - min-height: 321px; height: 100%; - padding: 10px 13px; - - @media (max-width: @screen-md-max) { - min-height: 330px; - } @media (max-width: @screen-sm-max) { padding-left: @padding-xs; @@ -912,30 +911,6 @@ } } - p.plans-table-th-content-title { - font-size: @font-size-large; - padding-bottom: @padding-sm; - border-bottom: 1px solid @gray-lighter; - margin-bottom: @margin-lg; - - @media (max-width: @screen-md-max) { - font-size: @font-size-base; - } - - // `plans-table-th-content-title` is visually invisible on screen size less than @screen-xs-max - // because there is a sticky header (`plans-v2-table-sticky-header` class) that "replace" the content visually - // (see the `@plans-table-sticky-header-z-index` variable that make the sticky header element is "above" the whole table) - // however, we still need to properly styling the `plans-table-th-content-title` for small screen size to - // fit this element to the size of the sticky header - // this trick is used because th element can not have a `position: sticky` rule, at least for our use case - @media (max-width: @screen-xs-max) { - min-height: 40px; - margin-bottom: @margin-md; - font-size: @font-size-small; - padding-bottom: 0; - } - } - p.plans-table-th-content-benefit, ul.plans-table-th-content-benefit { padding-top: 15px; @@ -961,8 +936,25 @@ font-weight: 700; } - .plans-v2-table-price-container { + .plans-table-price-container { position: relative; + + s { + position: absolute; + left: 0; + top: -27px; + font-weight: 700; + font-size: @font-size-small; + line-height: 42px; + display: flex; + justify-content: center; + width: 100%; + color: @ol-blue-gray-2; + + @media (max-width: @screen-xs-max) { + font-size: @font-size-extra-small; + } + } } p.plans-v2-table-price-period-label { @@ -987,22 +979,6 @@ } } - strike.plans-v2-table-price-before-discount { - position: absolute; - top: -27px; - font-weight: 700; - font-size: @font-size-small; - line-height: 42px; - display: flex; - justify-content: center; - width: 100%; - color: @ol-blue-gray-2; - - @media (max-width: @screen-xs-max) { - font-size: @font-size-extra-small; - } - } - small.plans-table-th-content-additional-link { text-transform: lowercase; margin-top: @margin-xs; @@ -1020,7 +996,6 @@ display: flex; justify-content: space-between; align-items: center; - padding: 6px 6px 6px 18px; i.plans-table-feature-question-icon { margin-left: 10px; @@ -1033,7 +1008,6 @@ @media (max-width: @screen-xs-max) { display: inline-block; text-align: left; - padding: 6px; width: 100%; background-color: @ol-blue-gray-0; min-height: @plans-table-td-mobile-min-height; @@ -1140,7 +1114,7 @@ flex: 1 1 0px; span { - margin: 0px @margin-xs; + margin: @margin-xs; border-bottom: 1px solid #cccccc; height: 100%; display: flex;