penpot/frontend/src/app/main/ui/settings/subscription.scss
Juanfran bd91036b95 Show nitrate checkout error on subscription page
When the Stripe checkout fails to start, the subscription page now
  shows an inline error in the Business Nitrate card under the CTA
  instead of a toast. When the post-payment activation fails, the toast
  message is updated to point users to support@penpot.app.

  The nitrate-form modal also passed a URI object to
  build-nitrate-callback-urls while the underlying append-query-param
  relied on lambdaisland's u/parse, which only accepts strings. Switched
  to the local u/uri helper so both strings and URI records work, so
  failures opened from the modal land on the subscription page.
2026-05-07 12:48:43 +02:00

426 lines
7.6 KiB
SCSS

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/typography.scss" as t;
@use "ds/_borders.scss" as *;
@use "ds/spacing.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/_utils.scss" as *;
.dashboard-section {
display: flex;
inline-size: 100%;
justify-content: center;
align-items: center;
}
.dashboard-content {
display: flex;
flex-direction: column;
max-inline-size: $sz-500;
margin-block-end: var(--sp-xxxl);
inline-size: px2rem(580);
margin: px2rem(92) auto px2rem(120);
justify-content: center;
}
.membership-container {
margin-block-start: var(--sp-l);
}
.membership {
align-items: center;
display: flex;
margin-block-start: var(--sp-s);
}
.membership-date {
@include t.use-typography("body-small");
color: var(--color-foreground-secondary);
margin-inline-start: var(--sp-s);
}
.subscription-member,
.penpot-member {
@extend %button-icon;
}
.penpot-member {
stroke: var(--icon-foreground);
}
.subscription-member {
stroke: var(--color-badge-premium);
}
.title-section {
@include t.use-typography("title-large");
color: var(--color-foreground-primary);
margin-block-end: var(--sp-xxl);
}
.plan-section-title {
@include t.use-typography("headline-small");
color: var(--color-foreground-primary);
}
.plan-card {
border: $b-1 solid var(--color-background-quaternary);
border-radius: var(--sp-s);
margin-block-start: var(--sp-l);
padding: var(--sp-l);
}
.plan-card-highlight {
background-color: var(--color-background-tertiary);
border: $b-1 solid var(--color-accent-select);
}
.plan-card-header {
display: flex;
justify-content: space-between;
margin-block-end: var(--sp-m);
}
.plan-card-title-container {
display: flex;
align-items: center;
gap: var(--sp-s);
}
.plan-title-icon {
@extend %button-icon;
stroke: var(--color-foreground-primary);
block-size: var(--sp-xl);
inline-size: var(--sp-xl);
border-radius: 6px;
border: 1.75px solid var(--color-foreground-primary);
stroke-width: 2.25px;
padding: px2rem(3);
}
.plan-title-icon svg {
block-size: var(--sp-m);
inline-size: var(--sp-m);
}
.plan-card-title,
.plan-price-value {
@include t.use-typography("title-medium");
color: var(--color-foreground-primary);
}
.plan-editors {
@include t.use-typography("body-medium");
align-self: end;
color: var(--color-foreground-primary);
margin-block-end: 2px;
}
.plan-price-period {
@include t.use-typography("body-small");
color: var(--color-foreground-primary);
}
.plan-cancel {
align-items: center;
background-color: var(--color-background-secondary);
border-radius: var(--sp-xs);
display: flex;
padding-inline: var(--sp-s);
}
.plan-cancel-date {
@include t.use-typography("body-medium");
color: var(--color-foreground-primary);
}
.benefits-list {
margin-block: 0;
}
.benefits-title,
.benefit {
@include t.use-typography("body-medium");
color: var(--color-foreground-secondary);
}
.other-subscriptions {
margin-block-start: px2rem(52);
}
.cta-button {
@include t.use-typography("body-medium");
@include deprecated.button-style;
align-items: center;
color: var(--color-accent-primary);
display: flex;
margin-block-start: var(--sp-m);
text-align: left;
}
.cta-button svg {
@extend %button-icon;
block-size: var(--sp-l);
inline-size: var(--sp-l);
stroke: var(--color-accent-primary);
margin-inline-start: var(--sp-xs);
}
.icon-dropdown svg {
transform: rotate(90deg);
}
.bottom-link {
margin-block-start: var(--sp-xs);
}
.bottom-button {
margin-block-start: var(--sp-xl);
}
.inline-error {
@include t.use-typography("body-small");
color: var(--color-foreground-error);
margin-block: var(--sp-s) 0;
}
.modal-overlay {
@extend %modal-overlay-base;
}
.modal-dialog {
@extend %modal-container-base;
max-block-size: initial;
min-inline-size: px2rem(548);
}
.modal-dialog.subscription-success {
min-inline-size: px2rem(648);
}
.close-btn {
@extend %modal-close-btn-base;
}
.modal-title {
@include t.use-typography("title-large");
margin-block-end: var(--sp-xxxl);
color: var(--modal-title-foreground-color);
display: flex;
gap: var(--sp-m);
}
.subscription-title {
margin-block-end: var(--sp-l);
}
.modal-text-medium {
@include t.use-typography("body-medium");
}
.modal-text-cap {
margin-inline-end: var(--sp-s);
}
.text-strikethrough {
text-decoration: line-through;
}
.modal-text-medium strong,
.text-strikethrough strong,
.modal-text-cap strong {
font-weight: deprecated.$fw700;
}
.modal-content,
.modal-end {
color: var(--color-foreground-secondary);
display: flex;
flex-direction: column;
}
.modal-success-content {
display: flex;
gap: $sz-40;
}
.modal-footer {
margin-block-start: $sz-40;
}
.action-buttons {
@extend %modal-action-btns;
}
.success-action-buttons {
margin-block-start: var(--sp-l);
}
.primary-button {
@extend %modal-accept-btn;
min-block-size: $sz-32;
block-size: auto;
}
.cancel-button {
@extend %modal-cancel-btn;
min-block-size: $sz-32;
white-space: break-spaces;
block-size: auto;
}
.modal-start {
display: flex;
justify-content: center;
max-inline-size: $sz-224;
@media (width <= 992px) {
display: none;
}
}
.modal-start svg {
inline-size: 100%;
block-size: auto;
}
.editors-text {
@include t.use-typography("body-medium");
margin: 0;
}
.editors-list-warning {
margin-inline-start: var(--sp-xl);
margin-block: var(--sp-s);
}
.editors-list {
@include t.use-typography("body-medium");
list-style-position: inside;
list-style-type: none;
margin-inline-start: var(--sp-xl);
max-block-size: px2rem(216);
overflow-y: auto;
}
.input-field {
--input-icon-padding: var(--sp-s);
inline-size: px2rem(80);
}
.error-message {
@include t.use-typography("body-small");
color: var(--color-foreground-error);
margin-block-start: var(--sp-s);
}
.editors-wrapper {
align-items: center;
display: flex;
gap: var(--sp-xl);
margin-block-start: var(--sp-l);
}
.editors-cost {
display: flex;
flex-direction: column;
}
.unlimited-capped-warning {
@include t.use-typography("body-small");
background-color: var(--color-background-tertiary);
border-radius: var(--sp-s);
margin-block-start: $sz-40;
padding-block: var(--sp-s);
padding-inline: var(--sp-m);
}
.show-editors-button {
padding-inline: 0;
}
.radio-btns {
display: flex;
flex-direction: column;
padding-block-end: var(--sp-xl);
gap: var(--sp-s);
}
.radio-btns label {
@include t.use-typography("body-large");
padding: 0;
display: flex;
align-items: center;
color: var(--color-foreground-secondary);
}
.modal-contact-content {
gap: var(--sp-xl);
}
.downgrade-warning {
@include t.use-typography("body-medium");
background-color: var(--color-background-tertiary);
border-radius: var(--sp-s);
padding-block: var(--sp-s);
padding-inline: var(--sp-m);
margin-block: var(--sp-m) var(--sp-xxxl);
}
.downgrade-list {
list-style-position: outside;
list-style-type: disc;
margin-block: var(--sp-l) 0;
padding-inline-start: var(--sp-l);
}
.downgrade-item {
@include t.use-typography("body-medium");
margin-block-end: var(--sp-l);
}
.cta-link {
@include t.use-typography("body-medium");
align-items: center;
color: var(--color-accent-primary);
display: flex;
margin-block-end: var(--sp-xxxl);
text-align: left;
text-decoration: underline;
}
.button-full-width {
justify-content: center;
inline-size: 100%;
}