Three-tier plan picker with a highlighted popular plan and a monthly/annual toggle.
Switch plans or cancel anytime. Annual billing saves you up to 17%.
For individuals shipping their first project.
For growing teams that need room to scale.
For organizations with advanced controls.
Install with the CLI, or add the packages and paste the source below.
Add Billing to your app with its source-owned dependencies.
npx cooud-ui add billing
Install the Cooud UI packages, then paste the block below.
Copy the source for Plan selector. Every class is a semantic token, so it re-themes with your app.
import {Badge,Button,Card,CardContent,CardFooter,CardHeader,CardTitle,Separator,Switch,} from "@cooud-ui/ui";import { Check } from "lucide-react";import { useState } from "react";interface Plan {id: string;name: string;tagline: string;monthly: number;annual: number;features: string[];cta: string;popular?: boolean;}const plans: Plan[] = [{id: "starter",name: "Starter",tagline: "For individuals shipping their first project.",monthly: 0,annual: 0,features: ["1 workspace", "Up to 3 seats", "5 GB storage", "Community support"],cta: "Get started",},{id: "team",name: "Team",tagline: "For growing teams that need room to scale.",monthly: 29,annual: 24,features: ["Unlimited workspaces","Up to 25 seats","250 GB storage","Priority email support","Usage analytics",],cta: "Upgrade to Team",popular: true,},{id: "enterprise",name: "Enterprise",tagline: "For organizations with advanced controls.",monthly: 89,annual: 74,features: ["Everything in Team","SSO & SCIM","Unlimited storage","Dedicated success manager","99.9% uptime SLA",],cta: "Contact sales",},];export function PlansBlock() {const [annual, setAnnual] = useState(true);return (<section aria-label="Choose a plan" className="flex w-full flex-col gap-6"><header className="flex flex-col items-center gap-4 text-center"><div className="flex flex-col gap-1"><h2 className="font-display text-2xl font-semibold text-fg">Pick the plan that fits</h2><p className="text-sm text-fg-secondary">Switch plans or cancel anytime. Annual billing saves you up to 17%.</p></div><div className="flex items-center gap-3"><span className={annual ? "text-sm text-fg-tertiary" : "text-sm font-medium text-fg"}>Monthly</span><Switch checked={annual} onCheckedChange={setAnnual} aria-label="Bill annually" /><span className={annual ? "text-sm font-medium text-fg" : "text-sm text-fg-tertiary"}>Annual</span><Badge variant="primary">Save 17%</Badge></div></header><div className="grid items-start gap-4 sm:grid-cols-3">{plans.map((plan) => {const price = annual ? plan.annual : plan.monthly;return (<Cardkey={plan.id}className={plan.popular? "relative gap-5 border-primary shadow-glow": "relative gap-5 shadow-sm"}>{plan.popular ? (<div className="absolute -top-3 left-1/2 -translate-x-1/2"><Badge variant="primary">Popular</Badge></div>) : null}<CardHeader><CardTitle className="font-display text-lg">{plan.name}</CardTitle><p className="col-span-full text-sm text-fg-secondary">{plan.tagline}</p></CardHeader><CardContent className="flex flex-col gap-5"><div className="flex items-baseline gap-1"><span className="font-display text-3xl font-semibold text-fg">${price}</span><span className="text-sm text-fg-tertiary">{price === 0 ? "forever" : annual ? "/ mo, billed yearly" : "/ month"}</span></div><Separator /><ul className="flex flex-col gap-3">{plan.features.map((feature) => (<li key={feature} className="flex items-start gap-2 text-sm text-fg"><Check className="mt-0.5 size-4 shrink-0 text-success" aria-hidden="true" /><span>{feature}</span></li>))}</ul></CardContent><CardFooter><Button variant={plan.popular ? "gradient" : "outline"} className="w-full">{plan.cta}</Button></CardFooter></Card>);})}</div></section>);}
Switch plans or cancel anytime. Annual billing saves you up to 17%.
For individuals shipping their first project.
For growing teams that need room to scale.
For organizations with advanced controls.