{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pricing-three-tiers",
  "title": "Three-tier pricing",
  "description": "Three plan cards with a monthly/yearly switch, a savings badge and a highlighted middle plan.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "badge",
    "button",
    "https://velora.colorlib.com/r/blur-fade.json",
    "https://velora.colorlib.com/r/border-beam.json",
    "https://velora.colorlib.com/r/grid-pattern.json",
    "https://velora.colorlib.com/r/number-ticker.json"
  ],
  "files": [
    {
      "path": "src/components/blocks/pricing-three-tiers.tsx",
      "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport { CheckIcon, SparklesIcon } from \"lucide-react\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { BlurFade } from \"@/components/velora/blur-fade\";\nimport { BorderBeam } from \"@/components/velora/border-beam\";\nimport { DotPattern } from \"@/components/velora/grid-pattern\";\nimport { NumberTicker } from \"@/components/velora/number-ticker\";\nimport { cn } from \"@/lib/utils\";\n\ntype Billing = \"monthly\" | \"yearly\";\n\nconst YEARLY_DISCOUNT = \"Save 20%\";\n\n/** Prices are per seat, per month. `yearly` is the monthly equivalent when billed annually. */\nconst PLANS = [\n  {\n    name: \"Starter\",\n    description:\n      \"For solo makers and small teams getting their first project out.\",\n    price: { monthly: 15, yearly: 12 },\n    cta: \"Start free trial\",\n    featured: false,\n    features: [\n      \"Up to 5 members\",\n      \"3 active projects\",\n      \"Docs and roadmaps\",\n      \"Community support\",\n      \"7-day version history\",\n    ],\n  },\n  {\n    name: \"Pro\",\n    description:\n      \"For growing teams that ship every week and need room to scale.\",\n    price: { monthly: 40, yearly: 32 },\n    cta: \"Start free trial\",\n    featured: true,\n    features: [\n      \"Unlimited members\",\n      \"Unlimited projects\",\n      \"Release automation\",\n      \"Guest access and client portals\",\n      \"Priority email support\",\n      \"90-day version history\",\n    ],\n  },\n  {\n    name: \"Scale\",\n    description: \"For organisations with security reviews, SSO and many teams.\",\n    price: { monthly: 90, yearly: 72 },\n    cta: \"Talk to sales\",\n    featured: false,\n    features: [\n      \"Everything in Pro\",\n      \"SAML SSO and SCIM\",\n      \"Audit log and data residency\",\n      \"99.9% uptime SLA\",\n      \"Dedicated success manager\",\n      \"Unlimited version history\",\n    ],\n  },\n] as const;\n\nconst usd = (n: number) => `$${n.toLocaleString(\"en-US\")}`;\n\n/**\n * Three plan cards with a monthly/yearly toggle. The toggle is a pair of\n * native radio buttons, so arrow keys and screen readers work for free; the\n * featured plan gets a travelling border beam.\n */\nexport function PricingThreeTiers() {\n  const [billing, setBilling] = useState<Billing>(\"monthly\");\n\n  return (\n    <section className=\"relative isolate overflow-hidden px-6 py-24 sm:py-32 lg:px-8\">\n      <DotPattern\n        aria-hidden\n        className=\"absolute inset-0 -z-10 size-full fill-foreground/10 [mask-image:radial-gradient(ellipse_at_top,black,transparent_65%)]\"\n      />\n      <div\n        aria-hidden\n        className=\"absolute inset-x-0 top-0 -z-10 mx-auto h-72 max-w-3xl rounded-full bg-gradient-to-r from-brand-from/15 via-brand-via/10 to-brand-to/15 blur-3xl\"\n      />\n\n      <div className=\"mx-auto max-w-7xl\">\n        <BlurFade className=\"mx-auto max-w-2xl text-center\">\n          <p className=\"text-sm font-medium text-primary\">Pricing</p>\n          <h2 className=\"mt-3 text-3xl font-semibold tracking-tight text-balance sm:text-5xl\">\n            Plans that grow with your team\n          </h2>\n          <p className=\"mt-5 text-lg text-pretty text-muted-foreground\">\n            Start free for 14 days on any plan. Switch or cancel whenever you\n            like — no contracts, no surprises.\n          </p>\n        </BlurFade>\n\n        <BlurFade delay={0.1} className=\"mt-10 flex justify-center\">\n          <fieldset>\n            <legend className=\"sr-only\">Billing period</legend>\n            <div className=\"inline-flex items-center gap-1 rounded-full border bg-background/70 p-1 backdrop-blur\">\n              {([\"monthly\", \"yearly\"] as const).map((option) => (\n                <label\n                  key={option}\n                  className={cn(\n                    \"group/billing relative inline-flex h-9 cursor-pointer items-center gap-2 rounded-full px-4 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground\",\n                    \"has-checked:bg-primary has-checked:text-primary-foreground has-checked:shadow-sm\",\n                    \"has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-ring\",\n                  )}\n                >\n                  <input\n                    type=\"radio\"\n                    name=\"pricing-three-tiers-billing\"\n                    value={option}\n                    checked={billing === option}\n                    onChange={() => setBilling(option)}\n                    className=\"sr-only\"\n                  />\n                  {option === \"monthly\" ? \"Monthly\" : \"Yearly\"}\n                  {option === \"yearly\" && (\n                    <Badge\n                      variant=\"secondary\"\n                      className=\"bg-primary/10 text-primary group-has-checked/billing:bg-primary-foreground/20 group-has-checked/billing:text-primary-foreground\"\n                    >\n                      {YEARLY_DISCOUNT}\n                    </Badge>\n                  )}\n                </label>\n              ))}\n            </div>\n          </fieldset>\n        </BlurFade>\n\n        {/* Announces the change once, instead of every price reading out */}\n        <p aria-live=\"polite\" className=\"sr-only\">\n          {billing === \"yearly\"\n            ? \"Showing yearly billing prices, 20% off.\"\n            : \"Showing monthly billing prices.\"}\n        </p>\n\n        <div className=\"mx-auto mt-12 grid max-w-md gap-6 lg:max-w-none lg:grid-cols-3\">\n          {PLANS.map((plan, i) => {\n            const price = plan.price[billing];\n            return (\n              <BlurFade\n                key={plan.name}\n                delay={0.15 + i * 0.08}\n                className={cn(\"h-full\", plan.featured && \"lg:-my-4\")}\n              >\n                <article\n                  className={cn(\n                    \"relative flex h-full flex-col rounded-3xl border bg-card p-8 shadow-sm\",\n                    plan.featured &&\n                      \"border-primary/30 bg-gradient-to-b from-primary/[0.07] to-card shadow-xl shadow-primary/10 lg:py-12\",\n                  )}\n                >\n                  {plan.featured && <BorderBeam size={120} duration={8} />}\n\n                  <div className=\"flex items-center justify-between gap-4\">\n                    <h3 className=\"text-lg font-semibold\">{plan.name}</h3>\n                    {plan.featured && (\n                      <Badge className=\"gap-1\">\n                        <SparklesIcon aria-hidden />\n                        Most popular\n                      </Badge>\n                    )}\n                  </div>\n                  <p className=\"mt-3 text-sm text-pretty text-muted-foreground\">\n                    {plan.description}\n                  </p>\n\n                  <p className=\"mt-8 flex items-baseline gap-1.5\">\n                    <NumberTicker\n                      value={price}\n                      startValue={plan.price.monthly}\n                      prefix=\"$\"\n                      className=\"text-5xl font-semibold tracking-tight\"\n                    />\n                    <span className=\"text-sm text-muted-foreground\">\n                      per seat / month\n                    </span>\n                  </p>\n                  <p className=\"mt-2 h-5 text-sm text-muted-foreground\">\n                    {billing === \"yearly\"\n                      ? `${usd(price * 12)} billed yearly`\n                      : \"Billed monthly\"}\n                  </p>\n\n                  <Button\n                    asChild\n                    size=\"lg\"\n                    variant={plan.featured ? \"default\" : \"outline\"}\n                    className=\"mt-8 h-11 w-full rounded-full\"\n                  >\n                    <a href=\"#\">\n                      {plan.cta}\n                      <span className=\"sr-only\"> — {plan.name} plan</span>\n                    </a>\n                  </Button>\n\n                  <ul className=\"mt-8 space-y-3 border-t pt-8 text-sm\">\n                    {plan.features.map((feature) => (\n                      <li key={feature} className=\"flex gap-3\">\n                        <CheckIcon\n                          aria-hidden\n                          className={cn(\n                            \"mt-0.5 size-4 shrink-0\",\n                            plan.featured\n                              ? \"text-primary\"\n                              : \"text-muted-foreground\",\n                          )}\n                        />\n                        {feature}\n                      </li>\n                    ))}\n                  </ul>\n                </article>\n              </BlurFade>\n            );\n          })}\n        </div>\n\n        <p className=\"mt-12 text-center text-sm text-muted-foreground\">\n          Prices in USD, excluding tax. Non-profits and schools get 50% off —{\" \"}\n          <a\n            href=\"#\"\n            className=\"font-medium text-foreground underline underline-offset-4 hover:text-primary\"\n          >\n            ask us\n          </a>\n          .\n        </p>\n      </div>\n    </section>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/blocks/pricing-three-tiers.tsx"
    }
  ],
  "categories": [
    "pricing-sections"
  ],
  "type": "registry:block"
}