STRIPE STARTER · PRICING UI
Pricing UI
PricingTable is the only component you need on your pricing page. It reads payment mode, hides the toggle for one-time, calculates yearly savings, highlights the popular plan. PricingCard and PricingToggle are its building blocks.
The pricing UI lives in src/components/pricing/. PricingTable is the orchestrator — drop it on a page and you have a working pricing section. The other two components (PricingCard, PricingToggle) are reusable pieces if you want to compose your own layout.
Drop-in usage
import { PricingTable } from "@/components/pricing/PricingTable";
export default function PricingPage() {
return (
<main className="py-24">
<PricingTable />
</main>
);
}What PricingTable does automatically
- Reads payment mode via usePaymentsConfig().
- Renders oneTimePlans, subscriptionPlans, or both — depending on mode.
- Shows PricingToggle (monthly/yearly) only when subscriptions are supported.
- Wires each card to CheckoutButton with the right Price ID for the current interval.
- Calculates yearly savings via getYearlySavings() and badges it on the toggle.
- Applies the "Most popular" treatment to whichever plan has highlighted: true.
usePricing — the interval toggle hook
import { usePricing } from "@/hooks/use-pricing";
const { interval, isYearly, isMonthly, toggleInterval } = usePricing();
// Pass `interval` to <PricingCard /> and <PricingToggle />.Composing your own layout
If you want a non-grid pricing layout (a single hero card, a comparison table, etc.), skip PricingTable and use the primitives directly.
import { PricingCard } from "@/components/pricing/PricingCard";
import { PricingToggle } from "@/components/pricing/PricingToggle";
import { usePricing } from "@/hooks/use-pricing";
import { subscriptionPlans } from "@/config/pricing";
const { interval, toggleInterval } = usePricing();
<PricingToggle interval={interval} onToggle={toggleInterval} />
{subscriptionPlans.map((plan) => (
<PricingCard key={plan.id} plan={plan} interval={interval} />
))}Don't restyle by editing src/components/ui/*
Those files are generated by shadcn/ui. Edit them and the next time you bump a primitive you'll fight the diff. Wrap them in src/components/pricing instead.
Highlighting more than one plan looks weird
highlighted: true is meant for ONE plan — the one you want to nudge people toward. Marking two breaks the visual hierarchy. Pick one.