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
ReactTailwind
TSX
npx @uiblox/cli add pricing-table

Preview

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"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>; }