From b5eab6a949662401bd6c15cfc5b04398f8e93213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marina=20L=C3=B3pez?= Date: Thu, 12 Nov 2026 12:35:13 +0100 Subject: [PATCH] :lipstick: Update promotional banner (#12944) --- frontend/resources/images/icons/pencil.svg | 3 + .../src/app/main/ui/dashboard/sidebar.cljs | 2 +- .../app/main/ui/dashboard/subscription.cljs | 66 ++++++++--- .../app/main/ui/dashboard/subscription.scss | 111 +++++++++++++++++- .../main/ui/ds/foundations/assets/icon.cljs | 1 + frontend/translations/en.po | 10 +- frontend/translations/es.po | 10 +- 7 files changed, 174 insertions(+), 29 deletions(-) create mode 100644 frontend/resources/images/icons/pencil.svg diff --git a/frontend/resources/images/icons/pencil.svg b/frontend/resources/images/icons/pencil.svg new file mode 100644 index 0000000000..50dfe16628 --- /dev/null +++ b/frontend/resources/images/icons/pencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index d9514fb927..ca85e0ea26 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -656,7 +656,7 @@ [:* (if (contains? cf/flags :admin-console) [:* - [:> nitrate-sidebar* {:profile profile :teams teams}] + [:> nitrate-sidebar* {:profile profile :teams teams :team team}] [:> nitrate-current-plan* {:profile profile}]] (when (contains? cf/flags :subscriptions) (if (show-subscription-dashboard-banner? profile) diff --git a/frontend/src/app/main/ui/dashboard/subscription.cljs b/frontend/src/app/main/ui/dashboard/subscription.cljs index c93644d90c..fa675fb9e2 100644 --- a/frontend/src/app/main/ui/dashboard/subscription.cljs +++ b/frontend/src/app/main/ui/dashboard/subscription.cljs @@ -118,8 +118,46 @@ :has-dropdown false :is-highlighted false}])))) +(mf/defc nitrate-enterprise-banner* + [{:keys [on-click button-label]}] + (let [collapsed* (mf/use-state false) + collapsed? (deref collapsed*) + toggle-collapse + (mf/use-fn #(swap! collapsed* not))] + + [:div {:class (stl/css-case :nitrate-banner true + :nitrate-enterprise-banner true + :collapsed collapsed?)} + [:button {:class (stl/css :nitrate-enterprise-toggle) + :type "button" + :aria-controls "nitrate-enterprise-content" + :aria-expanded (not collapsed?) + :on-click toggle-collapse} + [:> icon* {:icon-id i/pencil + :size "m" + :class (stl/css :nitrate-enterprise-pencil) + :aria-hidden true}] + [:span {:class (stl/css :nitrate-enterprise-title)} + (tr "subscription.dashboard.banner.unlock-enterprise")] + [:> icon* {:icon-id i/arrow-down + :size "m" + :class (stl/css :nitrate-enterprise-chevron) + :aria-hidden true}]] + [:div {:id "nitrate-enterprise-content" + :class (stl/css :nitrate-enterprise-panel) + :aria-hidden collapsed?} + [:div {:class (stl/css :nitrate-enterprise-panel-inner)} + [:span {:class (stl/css :nitrate-enterprise-description)} + (tr "subscription.dashboard.banner.unlock-features-description")] + [:> button* {:variant "primary" + :type "button" + :class (stl/css :nitrate-bottom-button) + :on-click on-click + :disabled collapsed?} + button-label]]]])) + (mf/defc nitrate-sidebar* - [{:keys [profile teams]}] + [{:keys [profile teams team]}] (let [nitrate? (dnt/is-valid-license? profile) nitrate-license (:subscription profile) manual-license? (:manual nitrate-license) @@ -151,6 +189,12 @@ subscription-type (if nitrate? (:type nitrate-license) (get-subscription-type (-> profile :props :subscription))) + show-unlock-features? + (and (contains? cf/flags :admin-console) + (not nitrate?) + (contains? #{"professional" "unlimited"} subscription-type) + (nil? (dm/get-in team [:organization :id]))) + team-count (count teams) account-age-days (dnt/account-age-days profile) @@ -210,19 +254,13 @@ :class (stl/css :nitrate-bottom-button) :on-click handle-go-to-cc} (tr "nitrate.activation-success.create-organization")]]] - ;; Banner for users without nitrate license - (when (not nitrate?) - [:div {:class (stl/css :nitrate-banner :highlighted)} - [:div {:class (stl/css :nitrate-content)} - [:span {:class (stl/css :nitrate-title)} (tr "subscription.dashboard.banner.unlock-features")]] - [:div {:class (stl/css :nitrate-content)} - [:span {:class (stl/css :nitrate-info)} (tr "subscription.dashboard.banner.unlock-features-description-text")] - [:> button* {:variant "primary" - :type "button" - :class (stl/css :nitrate-bottom-button) - :on-click handle-click} (if (:subscription profile) - (tr "subscription.dashboard.banner.upgrade-nitrate") - (tr "nitrate.form.try-free"))]]])) + ;; Banner for Professional/Unlimited users outside an organization + (when show-unlock-features? + [:> nitrate-enterprise-banner* + {:on-click handle-click + :button-label (if (:subscription profile) + (tr "subscription.dashboard.banner.upgrade-nitrate") + (tr "nitrate.form.try-free"))}])) ;; Banner for users with nitrate license almost expired or expired (when show-subscription-warning? diff --git a/frontend/src/app/main/ui/dashboard/subscription.scss b/frontend/src/app/main/ui/dashboard/subscription.scss index 4699b44d92..7d0bdcb0f0 100644 --- a/frontend/src/app/main/ui/dashboard/subscription.scss +++ b/frontend/src/app/main/ui/dashboard/subscription.scss @@ -208,25 +208,132 @@ } .nitrate-banner { + --nitrate-enterprise-gradient-start: var(--color-accent-success); + --nitrate-enterprise-gradient-end: var(--color-token-border); + + :global(.light) & { + --nitrate-enterprise-gradient-start: var(--color-background-info); + --nitrate-enterprise-gradient-end: var(--color-accent-primary-muted); + } + display: flex; border-radius: var(--sp-s); flex-direction: column; margin: var(--sp-m) var(--sp-m) 0; - background: var(--color-accent-select); + background: linear-gradient( + 110deg, + var(--nitrate-enterprise-gradient-start), + var(--nitrate-enterprise-gradient-end) + ); border: $b-1 solid var(--color-accent-primary-muted); padding: var(--sp-l); } +.nitrate-enterprise-banner { + display: grid; + grid-template-rows: auto minmax(0, 1fr); + background: linear-gradient( + 110deg, + var(--nitrate-enterprise-gradient-start), + var(--nitrate-enterprise-gradient-end) + ); + transition: grid-template-rows 240ms ease; +} + +.nitrate-enterprise-banner.collapsed { + grid-template-rows: auto minmax(0, 0fr); +} + +.nitrate-enterprise-toggle { + appearance: none; + background: transparent; + border: 0; + color: var(--color-foreground-primary); + cursor: pointer; + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + align-items: center; + gap: var(--sp-s); + inline-size: 100%; + padding: 0; + text-align: start; + font: inherit; + + &:focus-visible { + outline: var(--color-accent-primary) solid $b-2; + outline-offset: var(--sp-xxs); + border-radius: $br-4; + } +} + +.nitrate-enterprise-title { + @include use-typography("body-large"); + + color: var(--color-foreground-primary); + font-weight: 600; +} + +.nitrate-enterprise-pencil { + --icon-fill-color: currentcolor; + --icon-stroke-color: none; + + color: var(--color-foreground-primary); +} + +.nitrate-enterprise-chevron { + color: var(--color-foreground-secondary); + transition: transform 240ms ease; +} + +.collapsed .nitrate-enterprise-chevron { + transform: rotate(180deg); +} + +.nitrate-enterprise-panel { + min-block-size: 0; + overflow: hidden; + opacity: 1; + transition: opacity 180ms ease; +} + +.collapsed .nitrate-enterprise-panel { + opacity: 0; + pointer-events: none; +} + +.nitrate-enterprise-panel-inner { + display: flex; + flex-direction: column; + min-block-size: 0; + padding-block-start: var(--sp-s); +} + +.nitrate-enterprise-description { + @include use-typography("body-medium"); + + color: var(--color-foreground-primary); + margin-block-end: var(--sp-l); +} + +@media (prefers-reduced-motion: reduce) { + .nitrate-enterprise-banner, + .nitrate-enterprise-chevron, + .nitrate-enterprise-panel { + transition: none; + } +} + .nitrate-title { @include use-typography("body-large"); color: var(--color-foreground-primary); + font-weight: 600; } .nitrate-info { @include use-typography("body-medium"); - color: var(--color-foreground-secondary); + color: var(--color-foreground-primary); margin-block: var(--sp-s) var(--sp-xxl); } diff --git a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs index 6d05480deb..126cb7b4bc 100644 --- a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs +++ b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs @@ -223,6 +223,7 @@ (def ^:icon-id padding-top "padding-top") (def ^:icon-id padding-top-bottom "padding-top-bottom") (def ^:icon-id path "path") +(def ^:icon-id pencil "pencil") (def ^:icon-id pentool "pentool") (def ^:icon-id percentage "percentage") (def ^:icon-id picker "picker") diff --git a/frontend/translations/en.po b/frontend/translations/en.po index c0ef6a81ee..48ea44fed3 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -5803,14 +5803,12 @@ msgid "subscription.dashboard.banner.subscription-expired" msgstr "Your Enterprise subscription has expired. (%s)" #: src/app/main/ui/dashboard/subscription.cljs:217 -msgid "subscription.dashboard.banner.unlock-features" -msgstr "Unlock Enterprise features" +msgid "subscription.dashboard.banner.unlock-enterprise" +msgstr "Unlock Enterprise" #: src/app/main/ui/dashboard/subscription.cljs:219 -msgid "subscription.dashboard.banner.unlock-features-description-text" -msgstr "" -"Set fine-grained permissions and stay in control, without compromising the " -"open-source freedom your team loves." +msgid "subscription.dashboard.banner.unlock-features-description" +msgstr "For organizations that need advanced governance, centralized administration, and secure collaboration." #: src/app/main/ui/dashboard/subscription.cljs:224 msgid "subscription.dashboard.banner.upgrade-nitrate" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index c8506b8466..87d6b89e7d 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -5853,14 +5853,12 @@ msgid "subscription.dashboard.banner.subscription-expired" msgstr "Tu suscripción Enterprise ha caducado. (%s)" #: src/app/main/ui/dashboard/subscription.cljs:217 -msgid "subscription.dashboard.banner.unlock-features" -msgstr "Desbloquea las funciones Enterprise" +msgid "subscription.dashboard.banner.unlock-enterprise" +msgstr "Desbloquea Enterprise" #: src/app/main/ui/dashboard/subscription.cljs:219 -msgid "subscription.dashboard.banner.unlock-features-description-text" -msgstr "" -"Establece permisos detallados y mantén el control, sin renunciar a la " -"libertad del código abierto que tanto valora tu equipo." +msgid "subscription.dashboard.banner.unlock-features-description" +msgstr "Para organizaciones que necesitan una gobernanza avanzada, una administración centralizada y una colaboración segura." #: src/app/main/ui/dashboard/subscription.cljs:224 msgid "subscription.dashboard.banner.upgrade-nitrate"