Minimal Pricing
Original · freeminimal pricing tiers
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/pricex-minimal.json"use client";
import { useState } from "react";
import { motion, AnimatePresence, useReducedMotion } from "motion/react";
type Billing = "monthly" | "annually";
interface Tier {
id: string;
name: string;
tagline: string;
priceMonthly: number;
priceAnnually: number;
cta: string;
featured: boolean;
features: string[];
}
const TIERS: Tier[] = [
{
id: "starter",
name: "Starter",
tagline: "For individuals shaping their first workflow.",
priceMonthly: 0,
priceAnnually: 0,
cta: "Start for free",
featured: false,
features: [
"Up to 3 active projects",
"1 workspace member",
"7-day activity history",
"Core board & list views",
"Community support",
],
},
{
id: "pro",
name: "Pro",
tagline: "For small teams that ship every week.",
priceMonthly: 19,
priceAnnually: 15,
cta: "Start 14-day trial",
featured: true,
features: [
"Unlimited projects",
"Up to 10 members",
"Unlimited activity history",
"Custom fields, views & filters",
"Priority email support",
],
},
{
id: "scale",
name: "Scale",
tagline: "For orgs that need control and uptime.",
priceMonthly: 49,
priceAnnually: 39,
cta: "Contact sales",
featured: false,
features: [
"Everything in Pro",
"Unlimited members",
"SSO, SAML & audit logs",
"Granular roles & permissions",
"Dedicated success manager",
],
},
];
function CheckIcon({ className }: { className?: string }) {
return (
<svg
viewBox="0 0 20 20"
fill="none"
aria-hidden="true"
className={className}
>
<path
d="M4.5 10.5l3.5 3.5 7.5-8"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
function SparkIcon({ className }: { className?: string }) {
return (
<svg viewBox="0 0 20 20" fill="none" aria-hidden="true" className={className}>
<path
d="M10 2.5l1.6 4.4 4.4 1.6-4.4 1.6L10 14.5l-1.6-4.4L4 8.5l4.4-1.6L10 2.5z"
fill="currentColor"
/>
</svg>
);
}
export default function PricexMinimal() {
const shouldReduce = useReducedMotion();
const [billing, setBilling] = useState<Billing>("monthly");
const options: { id: Billing; label: string }[] = [
{ id: "monthly", label: "Monthly" },
{ id: "annually", label: "Annually" },
];
return (
<section className="pxmin-root relative w-full overflow-hidden bg-neutral-50 px-5 py-24 text-neutral-900 sm:px-6 sm:py-28 dark:bg-zinc-950 dark:text-zinc-50">
<style>{`
@keyframes pxmin-rise {
from { opacity: 0; transform: translateY(14px); }
to { opacity: 1; transform: none; }
}
@keyframes pxmin-float {
0%, 100% { transform: translate3d(0, 0, 0) scale(1); opacity: 0.55; }
50% { transform: translate3d(0, -18px, 0) scale(1.05); opacity: 0.8; }
}
.pxmin-glow {
animation: pxmin-float 9s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.pxmin-root *, .pxmin-root *::before, .pxmin-root *::after {
animation: none !important;
transition: none !important;
}
}
`}</style>
{/* decorative background */}
<div aria-hidden="true" className="pointer-events-none absolute inset-0 overflow-hidden">
<div className="pxmin-glow absolute left-1/2 top-[-6rem] h-72 w-72 -translate-x-1/2 rounded-full bg-indigo-300/40 blur-3xl dark:bg-indigo-600/20" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_1px_1px,rgba(15,23,42,0.05)_1px,transparent_0)] [background-size:22px_22px] dark:bg-[radial-gradient(circle_at_1px_1px,rgba(255,255,255,0.05)_1px,transparent_0)]" />
</div>
<div className="relative mx-auto max-w-6xl">
{/* header */}
<div className="mx-auto max-w-2xl text-center">
<span className="inline-flex items-center gap-1.5 rounded-full border border-indigo-200 bg-indigo-50 px-3 py-1 text-xs font-medium uppercase tracking-wider text-indigo-700 dark:border-indigo-500/30 dark:bg-indigo-500/10 dark:text-indigo-300">
<SparkIcon className="h-3.5 w-3.5" />
Pricing
</span>
<h2 className="mt-5 text-balance text-4xl font-semibold tracking-tight sm:text-5xl">
Simple pricing that scales with you
</h2>
<p className="mt-4 text-pretty text-base leading-relaxed text-neutral-600 dark:text-zinc-400">
Start free and upgrade the moment your team outgrows it. No seat games,
no surprise line items. Switch or cancel whenever you like.
</p>
</div>
{/* billing toggle */}
<div className="mt-9 flex items-center justify-center gap-3">
<div
role="radiogroup"
aria-label="Billing period"
className="relative inline-flex rounded-full border border-neutral-200 bg-white p-1 shadow-sm dark:border-zinc-800 dark:bg-zinc-900"
>
<span
aria-hidden="true"
className="absolute inset-y-1 left-1 w-[calc(50%-0.25rem)] rounded-full bg-neutral-900 shadow transition-transform duration-300 ease-out dark:bg-zinc-50"
style={{
transform:
billing === "annually" ? "translateX(100%)" : "translateX(0)",
}}
/>
{options.map((opt) => {
const active = billing === opt.id;
return (
<button
key={opt.id}
type="button"
role="radio"
aria-checked={active}
onClick={() => setBilling(opt.id)}
className={`relative z-10 rounded-full px-5 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-zinc-900 ${
active
? "text-white dark:text-zinc-900"
: "text-neutral-600 hover:text-neutral-900 dark:text-zinc-400 dark:hover:text-zinc-100"
}`}
>
{opt.label}
</button>
);
})}
</div>
<span className="hidden rounded-full bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-700 sm:inline-block dark:bg-emerald-500/15 dark:text-emerald-300">
Save 20%
</span>
</div>
{/* tiers */}
<div className="mt-14 grid grid-cols-1 gap-6 md:grid-cols-3 md:items-stretch">
{TIERS.map((tier, i) => {
const price =
billing === "monthly" ? tier.priceMonthly : tier.priceAnnually;
const isFree = tier.priceMonthly === 0;
return (
<motion.div
key={tier.id}
initial={shouldReduce ? false : { opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, amount: 0.3 }}
transition={{
duration: shouldReduce ? 0 : 0.45,
delay: shouldReduce ? 0 : i * 0.08,
ease: "easeOut",
}}
className={`relative flex flex-col rounded-2xl p-7 ${
tier.featured
? "border-2 border-indigo-500 bg-white shadow-xl shadow-indigo-500/10 md:-mt-4 md:mb-4 dark:border-indigo-500 dark:bg-zinc-900"
: "border border-neutral-200 bg-white/70 dark:border-zinc-800 dark:bg-zinc-900/60"
}`}
>
{tier.featured && (
<span className="absolute -top-3 left-1/2 inline-flex -translate-x-1/2 items-center gap-1 rounded-full bg-indigo-500 px-3 py-1 text-xs font-semibold text-white shadow-md">
<SparkIcon className="h-3 w-3" />
Most popular
</span>
)}
<div className="flex items-baseline justify-between">
<h3 className="text-lg font-semibold tracking-tight">
{tier.name}
</h3>
</div>
<p className="mt-1.5 min-h-[2.5rem] text-sm leading-relaxed text-neutral-600 dark:text-zinc-400">
{tier.tagline}
</p>
<div className="mt-6 flex items-end gap-1">
<span className="text-4xl font-semibold tracking-tight tabular-nums">
<AnimatePresence mode="popLayout" initial={false}>
<motion.span
key={billing}
initial={shouldReduce ? false : { opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={
shouldReduce ? { opacity: 0 } : { opacity: 0, y: -8 }
}
transition={{ duration: shouldReduce ? 0 : 0.22 }}
className="inline-block"
>
${price}
</motion.span>
</AnimatePresence>
</span>
<span className="pb-1 text-sm text-neutral-500 dark:text-zinc-500">
{isFree ? "forever" : "/ mo"}
</span>
</div>
<p className="mt-1 h-5 text-xs text-neutral-500 dark:text-zinc-500">
{isFree
? "No credit card required"
: billing === "annually"
? `Billed annually · $${price * 12}/yr`
: "Billed monthly"}
</p>
<button
type="button"
className={`mt-6 w-full rounded-xl px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-zinc-900 ${
tier.featured
? "bg-indigo-500 text-white hover:bg-indigo-600"
: "border border-neutral-300 bg-white text-neutral-900 hover:bg-neutral-100 dark:border-zinc-700 dark:bg-zinc-800/60 dark:text-zinc-50 dark:hover:bg-zinc-800"
}`}
>
{tier.cta}
</button>
<ul className="mt-7 space-y-3.5 border-t border-neutral-200/80 pt-6 dark:border-zinc-800">
{tier.features.map((feature) => (
<li key={feature} className="flex items-start gap-3 text-sm">
<span
className={`mt-0.5 flex h-5 w-5 flex-none items-center justify-center rounded-full ${
tier.featured
? "bg-indigo-100 text-indigo-600 dark:bg-indigo-500/20 dark:text-indigo-300"
: "bg-emerald-100 text-emerald-600 dark:bg-emerald-500/15 dark:text-emerald-400"
}`}
>
<CheckIcon className="h-3.5 w-3.5" />
</span>
<span className="text-neutral-700 dark:text-zinc-300">
{feature}
</span>
</li>
))}
</ul>
</motion.div>
);
})}
</div>
<p className="mt-12 text-center text-sm text-neutral-500 dark:text-zinc-500">
All plans include SSL, unlimited guests, and a 30-day money-back
guarantee.
</p>
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Simple Pricing
OriginalA three-tier pricing section with a highlighted popular plan.

Single Plan Pricing Card
OriginalA focused one-plan pricing card with price, trial badge, feature list, call to action and a money-back trust note, ideal when you sell a single flat-rate product.

Three Tier Pricing With Monthly Annual Toggle
OriginalA three-tier pricing grid with a pure-CSS monthly and annual billing toggle that swaps every price with no JavaScript, using a native checkbox and Tailwind group-has state.

Plan Feature Comparison Table
OriginalA responsive, semantic feature comparison table across three plans with grouped rows, tick and dash indicators and screen-reader labels so visitors can weigh every feature side by side.

Staggered Glow Pricing Tiers
OriginalA three-tier pricing section whose cards reveal in a staggered spring cascade, with a rotating conic-gradient glow on the popular plan and prices that count up smoothly when you toggle monthly and annual billing.

Spotlight Cursor Pricing Cards
OriginalPricing cards that light up with a cursor-following radial spotlight, drift over floating background orbs and rise into view with a staggered spring entrance, plus a pulsing glow on the popular plan.

Highlight Follow Pricing Plans
OriginalA pricing row where an animated gradient highlight glides via shared layout animation to whichever plan you hover, a three-way billing switch slides its pill, prices recount instantly and a perks marquee scrolls beneath.

Three Tier Pricing
Originalthree-tier pricing cards

Toggle Annual Pricing
Originalpricing with monthly/annual toggle

Single Highlight Pricing
Originalsingle highlighted plan

Comparison Table Pricing
Originalpricing comparison table

Cards Gradient Pricing
Originalgradient pricing cards

