Blox/
Pricing Table
A comparison pricing table with monthly/yearly toggle, feature lists, and highlighted popular plan. Essential for SaaS and subscription-based products.
Billing ToggleFeature ComparisonPopular Badge
Installation
Terminal
TSXReactTailwind
npx @uiblox/cli add pricing-tablePreview
MonthlyYearly -20%
Starter
$9/mo
- 5 Projects
- 10GB Storage
- Email Support
Popular
Pro
$29/mo
- Unlimited Projects
- 100GB Storage
- Priority Support
- Team Collaboration
Enterprise
$99/mo
- Everything in Pro
- Unlimited Storage
- Custom SLA
Source Code
pricing-table.tsx
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110"use client"; import { useState } from "react"; import { cn } from "@/lib/utils"; const plans = [ { name: "Starter", description: "Perfect for small projects", price: { monthly: 9, yearly: 7 }, features: ["5 Projects", "10GB Storage", "Basic Analytics", "Email Support"], cta: "Start Free Trial", popular: false, }, { name: "Pro", description: "For growing teams", price: { monthly: 29, yearly: 24 }, features: ["Unlimited Projects", "100GB Storage", "Advanced Analytics", "Priority Support", "Custom Integrations", "Team Collaboration"], cta: "Get Started", popular: true, }, { name: "Enterprise", description: "For large organizations", price: { monthly: 99, yearly: 79 }, features: ["Everything in Pro", "Unlimited Storage", "White-label Options", "Dedicated Account Manager", "Custom SLA", "On-premise Deployment"], cta: "Contact Sales", popular: false, }, ]; export function PricingTable() { const [billing, setBilling] = useState<"monthly" | "yearly">("monthly"); return ( <div className="py-12"> {/* Billing Toggle */} <div className="flex items-center justify-center gap-4 mb-10"> <span className={cn("text-sm", billing === "monthly" ? "text-slate-900 dark:text-white font-medium" : "text-slate-500")}>Monthly</span> <button onClick={() => setBilling(billing === "monthly" ? "yearly" : "monthly")} className="relative w-14 h-7 bg-purple-600 rounded-full transition-colors" > <div className={cn("absolute top-1 w-5 h-5 bg-white rounded-full transition-transform", billing === "yearly" ? "translate-x-8" : "translate-x-1")} /> </button> <span className={cn("text-sm", billing === "yearly" ? "text-slate-900 dark:text-white font-medium" : "text-slate-500")}> Yearly <span className="text-emerald-600 font-medium">(-20%)</span> </span> </div> {/* Plans */} <div className="grid md:grid-cols-3 gap-6 max-w-5xl mx-auto px-4"> {plans.map((plan) => ( <div key={plan.name} className={cn( "relative flex flex-col p-6 bg-white dark:bg-slate-900 rounded-2xl border", plan.popular ? "border-purple-500 shadow-lg shadow-purple-500/20" : "border-slate-200 dark:border-slate-800" )} > {plan.popular && ( <div className="absolute -top-3 left-1/2 -translate-x-1/2 px-3 py-1 bg-purple-600 text-white text-xs font-semibold rounded-full"> Most Popular </div> )} <div className="mb-6"> <h3 className="text-xl font-bold text-slate-900 dark:text-white">{plan.name}</h3> <p className="text-sm text-slate-500 mt-1">{plan.description}</p> </div> <div className="mb-6"> <span className="text-4xl font-bold text-slate-900 dark:text-white"> ${plan.price[billing]} </span> <span className="text-slate-500">/month</span> </div> <ul className="space-y-3 mb-6 flex-1"> {plan.features.map((feature) => ( <li key={feature} className="flex items-center gap-2 text-sm text-slate-600 dark:text-slate-400"> <CheckIcon className="text-emerald-500 flex-shrink-0" /> {feature} </li> ))} </ul> <button className={cn( "w-full py-3 rounded-xl font-semibold transition-colors", plan.popular ? "bg-purple-600 hover:bg-purple-700 text-white" : "bg-slate-100 dark:bg-slate-800 hover:bg-slate-200 dark:hover:bg-slate-700 text-slate-900 dark:text-white" )} > {plan.cta} </button> </div> ))} </div> </div> ); } function CheckIcon({ className }: { className?: string }) { return <svg className={`w-5 h-5 ${className}`} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" /></svg>; }