Featured
Pricing 2

Source Code
"use client"
import { Check } from "lucide-react"
import Link from "next/link"
import { useState } from "react"
import type { VariantProps } from "class-variance-authority"
import { Badge } from "@/components/ui/badge"
import { Button, buttonVariants } from "@/components/ui/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Switch } from "@/components/ui/switch"
import { IconType, LinkType } from "@/types"
interface PricingPlan {
title: string
description: string
price: {
monthly: string
yearly: string
}
features: string[]
button: {
label: string
link: LinkType
variant?: VariantProps<typeof buttonVariants>["variant"]
icon?: IconType
}
recommended?: boolean
}
interface Props {
badge: string
title: string
description: string
plans: PricingPlan[]
}
export default function Pricing2({ badge, title, description, plans }: Props) {
const [isYearly, setIsYearly] = useState(false)
return (
<div className="w-full py-20 lg:py-40">
<div className="container mx-auto">
<div className="flex text-center justify-center items-center gap-4 flex-col">
{badge && <Badge>{badge}</Badge>}
<div className="flex gap-2 flex-col">
{title && (
<h2 className="text-3xl md:text-5xl tracking-tighter max-w-xl text-center font-regular">
{title}
</h2>
)}
{description && (
<p className="text-lg leading-relaxed tracking-tight text-muted-foreground max-w-xl text-center">
{description}
</p>
)}
</div>
<div className="flex items-center gap-4 mt-8">
<span
className={`text-sm ${
!isYearly ? "text-foreground" : "text-muted-foreground"
}`}
>
Monthly
</span>
<Switch checked={isYearly} onCheckedChange={setIsYearly} />
<span
className={`text-sm ${
isYearly ? "text-foreground" : "text-muted-foreground"
}`}
>
Yearly <span className="text-primary">Save 20%</span>
</span>
</div>
</div>
<div className="grid pt-20 text-left grid-cols-1 lg:grid-cols-3 w-full gap-8">
{plans.map((plan, index) => (
<Card
key={index}
className={`w-full rounded-md relative ${
plan.recommended ? "border-primary shadow-lg" : ""
}`}
>
{plan.recommended && (
<div className="absolute -top-4 left-1/2 -translate-x-1/2">
<Badge variant="default" className="px-4 py-1">
Most Popular
</Badge>
</div>
)}
<CardHeader>
<CardTitle>{plan.title}</CardTitle>
<CardDescription>{plan.description}</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-col gap-8 justify-start">
<div className="flex flex-col gap-1">
<p className="flex flex-row items-center gap-2">
<span className="text-4xl font-bold">
{isYearly ? plan.price.yearly : plan.price.monthly}
</span>
<span className="text-sm text-muted-foreground">
/ {isYearly ? "year" : "month"}
</span>
</p>
{isYearly && (
<p className="text-sm text-muted-foreground">
Billed annually
</p>
)}
</div>
<div className="flex flex-col gap-4 justify-start">
{plan.features.map((feature, index) => (
<div key={index} className="flex flex-row gap-4">
<Check className="w-4 h-4 mt-2 text-primary" />
<div className="flex flex-col">
<p>{feature}</p>
</div>
</div>
))}
</div>
<Link
href={plan.button.link.href || "#"}
className="inline-block"
>
<Button
size="lg"
className="gap-4 w-full"
variant={
plan.recommended
? "default"
: plan.button.variant || "outline"
}
>
{plan.button.label}
{plan.button.icon}
</Button>
</Link>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</div>
)
}