registry/default/sections/pricing-3.tsx
"use client";
import { Check } from "lucide-react";
import * as React from "react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
// Decorative rainbow stripe
function RainbowStripe({ className }: { className?: string }) {
return (
<svg className={cn("h-16 w-12", className)} viewBox="0 0 60 80">
<path d="M10 0 L50 80" fill="none" stroke="#e53935" strokeWidth="8" />
<path d="M18 0 L58 80" fill="none" stroke="#fdd835" strokeWidth="8" />
<path d="M26 0 L66 80" fill="none" stroke="#43a047" strokeWidth="8" />
<path d="M34 0 L74 80" fill="none" stroke="#1e88e5" strokeWidth="8" />
</svg>
);
}
const plans = [
{
featured: false,
featureGroups: [
{
items: [
"1 free guided meditation monthly",
"Seasonal wellness tips via email",
"Community forum access",
],
title: "Features:",
},
{
items: ["Access to 3 yoga classes (pre-recorded)"],
title: "Classes:",
},
],
id: "gentle",
isPrice: false,
name: "Gentle Start",
price: "Free-forever",
subtitle: "Begin with Curiosity",
tagColor: "text-[#2a7d5f]",
},
{
featured: true,
featureGroups: [
{
items: [
"2 live sessions weekly",
"10% off retreats & workshops",
"Exclusive member community",
"Free downloadable guides",
"SSO & enhanced security",
],
title: "Features:",
},
{
items: ["Unlimited on-demand classes"],
title: "Classes:",
},
],
id: "mindful",
name: "Mindful Flow",
period: "/mo (billed annually)",
price: 19,
spotsLeft: 8,
subtitle: "Begin with Curiosity",
tagColor: "text-[#c9463d]",
},
{
featured: false,
featureGroups: [
{
items: [
"Unlimited 1:1 virtual check-ins",
"25% off wellness products",
"Gift a membership at 50% off",
"Custom wellness plans",
"VIP sessions + global summit access",
"2 guest passes/month",
],
title: "Features:",
},
{
items: [
"Access to 3 yoga classes (pre-recorded)",
"Advanced & offline class access",
],
title: "Classes:",
},
],
id: "unlimited",
name: "Unlimited Serenity",
period: "/mo (billed annually)",
price: 29,
subtitle: "Deepen Your Journey",
tagColor: "text-[#c9463d]",
},
];
export function Pricing3() {
const [billing, setBilling] = React.useState<"monthly" | "yearly">("monthly");
return (
<section className="w-full bg-[#f7f5ef] py-16 md:py-24">
<div className="mx-auto w-full max-w-6xl px-6">
{/* Header */}
<div className="mb-10 text-center">
<span className="mb-4 block text-gray-600 text-sm dark:text-gray-400">
Pricing Tiers
</span>
<h2 className="mb-2 font-serif text-4xl text-gray-900 leading-tight md:text-5xl dark:text-gray-100">
Nurture Your Practice,
</h2>
<div className="relative inline-block">
<span className="font-serif text-4xl text-[#c9463d] italic md:text-5xl">
Your Budget
</span>
{/* Underline decoration */}
<svg
className="absolute -bottom-2 left-0 h-3 w-full"
fill="none"
viewBox="0 0 200 12"
>
<path
d="M2 8 Q50 2 100 8 Q150 14 198 6"
fill="none"
stroke="#c9463d"
strokeLinecap="round"
strokeWidth="2"
/>
</svg>
</div>
</div>
{/* Billing Toggle */}
<div className="mb-12 flex justify-center">
<div className="inline-flex rounded-full border border-neutral-300 bg-white p-1">
<button
className={cn(
"rounded-full px-6 py-2 font-medium text-sm transition-colors",
billing === "monthly"
? "bg-white text-gray-900 shadow-sm dark:text-gray-100"
: "text-gray-600 dark:text-gray-400",
)}
onClick={() => setBilling("monthly")}
>
Monthly
</button>
<button
className={cn(
"flex items-center gap-2 rounded-full px-6 py-2 font-medium text-sm transition-colors",
billing === "yearly"
? "bg-white text-gray-900 shadow-sm dark:text-gray-100"
: "text-gray-600 dark:text-gray-400",
)}
onClick={() => setBilling("yearly")}
>
Yearly <span className="text-[#c9463d]">15% OFF</span>
</button>
</div>
</div>
{/* Pricing Cards */}
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
{plans.map((plan) => (
<div
className={cn(
"relative flex flex-col rounded-2xl p-6",
plan.featured
? "border-2 border-[#3d5a45] bg-[#3d5a45] text-white"
: "border border-gray-200 bg-white dark:border-neutral-700 dark:bg-background",
)}
key={plan.id}
>
{/* Rainbow decoration for featured */}
{plan.featured && (
<RainbowStripe className="absolute top-4 right-4 opacity-80" />
)}
{/* Plan Name */}
<span className={cn("mb-2 font-medium text-sm", plan.tagColor)}>
{plan.name}
</span>
{/* Price */}
<div className="mb-4">
{plan.isPrice === false ? (
<span className="font-semibold font-serif text-3xl">
{plan.price}
</span>
) : (
<div className="flex items-baseline gap-1">
<span className="font-normal text-3xl">
$
{billing === "yearly"
? Math.round((plan.price as number) * 0.85)
: plan.price}
</span>
<span
className={cn(
"text-sm",
plan.featured
? "text-white/70"
: "text-gray-600 dark:text-gray-400",
)}
>
{plan.period}
</span>
</div>
)}
</div>
{/* Subtitle & Features Card */}
<div
className={cn(
"flex-1 rounded-xl p-4",
plan.featured
? "bg-white text-gray-900 dark:text-gray-100"
: "bg-transparent",
)}
>
<p className="mb-4 font-semibold text-gray-900 dark:text-gray-100">
{plan.subtitle}
</p>
{plan.featureGroups.map((group) => (
<div className="mb-4" key={group.title}>
<p className="mb-2 text-gray-600 text-sm dark:text-gray-400">
{group.title}
</p>
<ul className="space-y-2">
{group.items.map((item, index) => {
const k = `feature_icon${index}`;
return (
<li
className="flex items-start gap-2 text-gray-700 text-sm dark:text-gray-300"
key={k}
>
<Check className="mt-0.5 h-4 w-4 shrink-0 text-[#2a7d5f]" />
{item}
</li>
);
})}
</ul>
</div>
))}
</div>
{/* CTA Button */}
<Button
className={cn(
"mt-4 h-11 w-full rounded-xl",
plan.featured
? "bg-[#3d5a45] text-white hover:bg-[#2d4535]"
: "border-neutral-300 text-[#2a7d5f] hover:bg-gray-50 dark:bg-neutral-900",
)}
variant={plan.featured ? "default" : "outline"}
>
Start today
</Button>
{/* Spots left */}
{plan.spotsLeft && (
<p className="mt-3 text-center text-neutral-400 text-xs">
*{plan.spotsLeft} spots for member left
</p>
)}
</div>
))}
</div>
</div>
</section>
);
}
export default Pricing3;