fix(billing): theme pricing cards and align action spacing

(cherry picked from commit 23b6abf235)
This commit is contained in:
yyh committed 2026-11-10 18:48:57 +08:00
1 parent 5da3151145
commit 486bba5bea
6 files changed
+128 -48

No files matched your search

@@ -21,7 +21,7 @@ export function PricingDialogContent() {
return (
<>
<DialogBackdrop className="transition-none" />
<DialogPopup className="fixed inset-0 size-full overflow-hidden bg-white transition-none data-ending-style:scale-100 data-ending-style:opacity-100 data-starting-style:scale-100 data-starting-style:opacity-100">
<DialogPopup className="fixed inset-0 size-full overflow-hidden bg-background-default transition-none data-ending-style:scale-100 data-ending-style:opacity-100 data-starting-style:scale-100 data-starting-style:opacity-100">
<DialogClose
render={
<IconButton
@@ -25,7 +25,7 @@ export function PricingFooter() {
</div>
<Link
href={pricingPageURL}
className="group flex h-fit min-w-0 items-center gap-x-1 rounded-xs system-md-regular text-saas-dify-blue-accessible focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-state-accent-solid xl:shrink-0"
className="group flex h-fit min-w-0 items-center gap-x-1 rounded-xs system-md-regular text-text-accent focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-state-accent-solid xl:shrink-0"
target="_blank"
rel="noopener noreferrer"
>
@@ -8,7 +8,14 @@ export default function Header() {
return (
<div className={styles.header}>
<DialogTitle className={styles.title}>
<img src="/logo/logo.svg" alt="Dify" width={60} height={27} />
<img src="/logo/logo.svg" alt="Dify" width={60} height={27} className="dark:hidden" />
<img
src="/pricing/logo-dark.svg"
alt="Dify"
width={60}
height={27}
className="hidden dark:block"
/>
<span>Cloud</span>
</DialogTitle>
<DialogDescription className={styles.description}>
@@ -215,25 +215,32 @@ export function CloudPlanItem({ plan, billingInterval, billing }: CloudPlanItemP
</>
)}
</div>
{showPlanButton && (
<div className="relative">
<Button
data-plan={plan}
variant="tertiary"
size={null}
disabled={isPlanDisabled}
className={styles.planButton}
onClick={handlePlanButtonClick}
>
<span className="min-w-0">{buttonLabel}</span>
</Button>
{educationDiscountWarningText && (
<div className="absolute inset-x-0 top-full mt-1.5 text-start system-2xs-medium text-text-tertiary">
{educationDiscountWarningText}
</div>
)}
</div>
)}
<div className={styles.actionSlot}>
{showPlanButton && (
<>
<Button
data-plan={plan}
data-promoted={
(currentPlan === 'sandbox' && plan === 'professional') ||
(currentPlan === 'professional' && plan === 'team') ||
undefined
}
variant="tertiary"
size={null}
disabled={isPlanDisabled}
className={styles.planButton}
onClick={handlePlanButtonClick}
>
<span className="min-w-0">{buttonLabel}</span>
</Button>
{educationDiscountWarningText && (
<div className="absolute inset-x-0 top-full mt-1.5 text-start system-2xs-medium text-text-tertiary">
{educationDiscountWarningText}
</div>
)}
</>
)}
</div>
</div>
<CloudPlanFeatures plan={plan} />
<Dialog open={showEducationPricingConfirm} onOpenChange={setShowEducationPricingConfirm}>
@@ -29,16 +29,41 @@
.content {
--pricing-ink: #010916;
--pricing-muted: #57657a;
--pricing-blue: #0033ff;
--pricing-switch: #e1e2e5;
--pricing-switch-border: #d8dadd;
--pricing-subdued: #959eab;
--pricing-card-border: #cec2b6;
--pricing-button-bg: #f8f7f7;
--pricing-button-border: var(--pricing-muted);
--pricing-feature-border: #f2f3f8;
--pricing-info: #b9bece;
position: relative;
isolation: isolate;
min-height: 100%;
padding: 40px 52px 24px;
color: var(--pricing-ink);
background: #fff;
background: var(--color-background-default);
font-family: PricingSohne, Arial, sans-serif;
}
/* Light cards use the website palette. The dark surface uses product theme tokens. */
:global(html[data-theme='dark']) .content {
--pricing-ink: var(--color-text-primary);
--pricing-muted: var(--color-text-secondary);
--pricing-switch: var(--color-background-section);
--pricing-switch-border: var(--color-divider-regular);
--pricing-subdued: var(--color-text-tertiary);
--pricing-card-border: var(--color-divider-regular);
--pricing-button-bg: var(--color-components-button-secondary-bg);
--pricing-button-border: var(--color-divider-regular);
--pricing-feature-border: var(--color-divider-subtle);
--pricing-info: var(--color-text-quaternary);
}
:global(html[data-theme='dark']) .content::before {
content: none;
}
.content::before {
position: absolute;
inset: 0;
@@ -63,7 +88,7 @@
}
.description {
margin-top: 3px;
color: #676f83;
color: var(--color-text-tertiary);
font-family: PricingInter, sans-serif;
font-size: 16px;
line-height: 24px;
@@ -83,9 +108,9 @@
margin: 32px auto;
gap: 0;
padding: 4px;
border: 1px solid #d8dadd;
border: 1px solid var(--pricing-switch-border);
border-radius: 100px;
background: #e1e2e5;
background: var(--pricing-switch);
}
.intervalOption {
display: flex;
@@ -96,22 +121,22 @@
min-width: 190px;
padding: 4px 24px;
border-radius: 100px;
color: #959eab;
color: var(--pricing-subdued);
font-size: 24px;
line-height: 30px;
font-weight: 500;
cursor: pointer;
}
.intervalOption[data-checked] {
background: white;
background: var(--color-components-button-secondary-bg);
color: var(--pricing-ink);
}
.intervalOption:focus-visible {
outline: 2px solid var(--pricing-blue);
outline: 2px solid var(--color-text-accent);
outline-offset: 3px;
}
.savings {
color: var(--pricing-blue);
color: var(--color-text-accent);
font-family: PricingInter, sans-serif;
font-size: 20px;
font-weight: 600;
@@ -125,9 +150,9 @@
min-width: 0;
min-height: 750px;
padding: 40px 23px 44px;
border: 1px solid #cec2b6;
border: 1px solid var(--pricing-card-border);
border-radius: 16px;
background: white;
background: var(--color-background-default);
}
.cardHeader {
display: flex;
@@ -160,8 +185,9 @@
line-height: 15px;
font-weight: 600;
text-transform: uppercase;
background: var(--pricing-blue);
color: white;
border-radius: 4px;
background: var(--color-state-accent-hover-alt);
color: var(--color-text-accent);
}
.planDescription {
position: relative;
@@ -186,26 +212,30 @@
font-weight: 500;
}
.card[data-plan='professional'] .priceAmount {
color: var(--pricing-blue);
color: var(--color-text-primary);
}
.priceSuffix {
font-size: 20px;
line-height: 25px;
}
.originalPrice {
color: #959eab;
color: var(--pricing-subdued);
font-size: 20px;
line-height: 25px;
text-decoration: line-through;
}
.actionSlot {
position: relative;
min-height: 60px;
}
.planButton {
width: 100%;
min-height: 60px;
height: auto;
padding: 12px;
border: 1px solid var(--pricing-muted);
border: 1px solid var(--pricing-button-border);
border-radius: 8px;
background: #f8f7f7;
background: var(--pricing-button-bg);
color: var(--pricing-muted);
font-family: inherit;
font-size: 24px;
@@ -215,15 +245,15 @@
box-shadow: none;
}
.planButton:not(:disabled):hover {
background: #eee;
background: var(--color-components-button-secondary-bg-hover);
}
.planButton[data-plan='professional'] {
border-color: var(--pricing-blue);
background: var(--pricing-blue);
.planButton[data-promoted] {
border-color: var(--color-saas-dify-blue-static);
background: var(--color-saas-dify-blue-static);
color: white;
}
.planButton[data-plan='professional']:not(:disabled):hover {
background: #0029cc;
.planButton[data-promoted]:not(:disabled):hover {
background: var(--color-saas-dify-blue-static-hover);
}
.planButton:disabled {
cursor: default;
@@ -240,7 +270,7 @@
gap: 6px;
min-height: 20px;
padding-bottom: 2px;
border-bottom: 1px solid #f2f3f8;
border-bottom: 1px solid var(--pricing-feature-border);
font-size: 14px;
line-height: 17px;
}
@@ -248,7 +278,7 @@
flex: none;
width: 4px;
height: 7px;
background: radial-gradient(circle at 2px 5px, var(--pricing-blue) 2px, transparent 2px);
background: radial-gradient(circle at 2px 5px, var(--color-text-accent) 2px, transparent 2px);
}
.featureLabel {
flex: 1;
@@ -260,7 +290,7 @@
width: 18px;
height: 18px;
margin: -4px;
color: #b9bece;
color: var(--pricing-info);
}
.footer {
display: flex;
+36
View File
@@ -0,0 +1,36 @@
<svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="60" height="27" viewBox="0 0 60 27" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Dify Logo">
<g id="if">
<use xlink:href="#stroke0_0_291" fill="#E8E8E8"/>
<use xlink:href="#stroke1_0_291" fill="#E8E8E8"/>
<mask id="stroke2_0_291" fill="white">
<use xlink:href="#stroke0_0_291"/>
<use xlink:href="#stroke1_0_291"/>
</mask>
<path d="M26.5002 4.72629C28.2041 4.72629 28.8333 3.6691 28.8333 2.36428C28.8333 1.05946 28.203 0.0022722 26.5002 0.0022722C24.7975 0.0022722 24.1672 1.05946 24.1672 2.36428C24.1672 3.6691 24.7975 4.72629 26.5002 4.72629ZM34.667 5.23226V6.75138H30.8335V10.1265H34.667V18.5638H28.3335V6.75257H19.9998V10.1277H24.667V18.565H19.1672V21.9401H44.1672V18.565H38.3335V10.1277H44.1672V6.75257H38.3335V3.37742H44.1672V0.0022722H39.834C36.9847 0.0022722 34.667 2.3488 34.667 5.23345V5.23226Z" stroke-width="0.5" stroke="url(#paint0_linear_0_291)" mask="url(#stroke2_0_291)"/>
</g>
<g id="Dy">
<use xlink:href="#stroke3_0_291" fill="#E8E8E8"/>
<use xlink:href="#stroke4_0_291" fill="#E8E8E8"/>
<mask id="stroke5_0_291" fill="white">
<use xlink:href="#stroke3_0_291"/>
<use xlink:href="#stroke4_0_291"/>
</mask>
<path d="M7.08373 0.00119033H0V21.9367H7.08373C15.8337 21.9367 18.3337 16.8746 18.3337 10.9683C18.3337 5.06213 15.8337 0 7.08373 0V0.00119033ZM7.16722 18.5627H4.00047V3.37634H7.16722C12.1978 3.37634 14.3333 5.87645 14.3333 10.9695C14.3333 16.0626 12.1978 18.5627 7.16722 18.5627ZM56.0419 6.75149L52.7081 17.7198L49.3744 6.75149H45.4163L50.2516 20.9402C50.7549 22.4177 49.9036 23.6249 48.3608 23.6249H46.6663V27H49.1569C51.3288 27 53.2832 25.6095 54.0181 23.5403L60 6.75149H56.0419Z" stroke-width="0.5" stroke="url(#paint1_linear_0_291)" mask="url(#stroke5_0_291)"/>
</g>
</g>
<defs>
<linearGradient id="paint0_linear_0_291" x1="-0.625267" y1="-0.420705" x2="59.6299" y2="26.8573" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E8E8E8"/>
</linearGradient>
<linearGradient id="paint1_linear_0_291" x1="-8.16958e-08" y1="-0.420815" x2="60.2552" y2="26.8572" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E8E8E8"/>
</linearGradient>
<path id="stroke0_0_291" d="M26.5002 4.72629C28.2041 4.72629 28.8333 3.6691 28.8333 2.36428C28.8333 1.05946 28.203 0.0022722 26.5002 0.0022722C24.7975 0.0022722 24.1672 1.05946 24.1672 2.36428C24.1672 3.6691 24.7975 4.72629 26.5002 4.72629Z"/>
<path id="stroke1_0_291" d="M34.667 5.23226V6.75138H30.8335V10.1265H34.667V18.5638H28.3335V6.75257H19.9998V10.1277H24.667V18.565H19.1672V21.9401H44.1672V18.565H38.3335V10.1277H44.1672V6.75257H38.3335V3.37742H44.1672V0.0022722H39.834C36.9847 0.0022722 34.667 2.3488 34.667 5.23345V5.23226Z"/>
<path id="stroke3_0_291" d="M7.08373 0.00119033H0V21.9367H7.08373C15.8337 21.9367 18.3337 16.8746 18.3337 10.9683C18.3337 5.06213 15.8337 0 7.08373 0V0.00119033ZM7.16722 18.5627H4.00047V3.37634H7.16722C12.1978 3.37634 14.3333 5.87645 14.3333 10.9695C14.3333 16.0626 12.1978 18.5627 7.16722 18.5627Z"/>
<path id="stroke4_0_291" d="M56.0419 6.75149L52.7081 17.7198L49.3744 6.75149H45.4163L50.2516 20.9402C50.7549 22.4177 49.9036 23.6249 48.3608 23.6249H46.6663V27H49.1569C51.3288 27 53.2832 25.6095 54.0181 23.5403L60 6.75149H56.0419Z"/>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB