{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pricing-tier",
  "type": "registry:ui",
  "title": "Pricing tier",
  "description": "One pricing plan as a card. The price has a spoken form, a feature that is not included says so in words, and you can mark a plan as recommended.",
  "categories": [
    "atom"
  ],
  "dependencies": [
    "lucide-react@^1.47.0"
  ],
  "registryDependencies": [
    "https://facadeui.dev/r/badge.json",
    "https://facadeui.dev/r/button.json",
    "https://facadeui.dev/r/heading.json",
    "https://facadeui.dev/r/types.json",
    "https://facadeui.dev/r/utils.json"
  ],
  "files": [
    {
      "path": "src/ui/pricing-tier.tsx",
      "type": "registry:ui",
      "target": "components/ui/pricing-tier.tsx",
      "content": "/**\n * PricingTier — one plan card: name, price, feature list, and a call to action.\n *\n * a11y: three things worth spelling out.\n *\n * 1. The price is split into a visible form and a spoken form, because \"$29/mo\"\n *    is read as \"dollar twenty nine slash m o\". `srPrice` fixes that.\n * 2. Features are a real `<ul>`, and a feature marked `included: false` gets\n *    visually hidden \"Not included\" text — a struck-through row with a grey\n *    cross conveys nothing without sight.\n * 3. The \"Most popular\" flag is a `Badge` with text, not a coloured border, and\n *    it is referenced from the tier's accessible name via `aria-describedby`.\n *\n * The card is a `<li>` by default: a pricing table is a list of plans.\n *\n * Dependencies: lucide-react, react, @/lib/types, @/lib/utils, ./badge, ./button,\n * ./heading.\n */\n\nimport { CheckIcon, XIcon } from \"lucide-react\"\nimport type { ElementType, ReactNode } from \"react\"\n\nimport type { CtaItem, HeadingLevel, LinkComponent } from \"@/lib/types\"\nimport { cn, slugId } from \"@/lib/utils\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { buttonVariants } from \"@/components/ui/button\"\nimport { Heading } from \"@/components/ui/heading\"\n\nexport interface PricingFeature {\n  label: string\n  /** Default `true`. `false` renders a struck row with hidden \"Not included\". */\n  included?: boolean\n  /** Extra detail shown under the feature. */\n  note?: string\n}\n\nexport interface PricingTierItem {\n  name: string\n  /** Display form, e.g. `\"$29\"`. */\n  price: string\n  /** Spoken form, e.g. `\"29 dollars\"`. Strongly recommended. */\n  srPrice?: string\n  /** Billing cadence, e.g. `\"/month\"`. */\n  period?: string\n  description?: string\n  features: PricingFeature[]\n  cta: CtaItem\n  /** Marks this tier as the recommended one. */\n  featured?: boolean\n  /** Text for the featured flag. Defaults to `\"Most popular\"`. */\n  featuredLabel?: string\n  /** Small print under the CTA. */\n  footnote?: string\n}\n\nexport interface PricingTierProps extends PricingTierItem {\n  link?: LinkComponent\n  /** Heading level of the plan name. Defaults to `3`, below a section `<h2>`. */\n  headingLevel?: HeadingLevel\n  as?: \"li\" | \"div\"\n  className?: string\n  children?: ReactNode\n}\n\nexport function PricingTier({\n  name,\n  price,\n  srPrice,\n  period,\n  description,\n  features,\n  cta,\n  featured = false,\n  featuredLabel = \"Most popular\",\n  footnote,\n  link,\n  headingLevel = 3,\n  as = \"li\",\n  className,\n  children,\n}: PricingTierProps) {\n  const Link = (link ?? \"a\") as ElementType\n  const Root = as as ElementType\n  const flagId = featured ? `${slugId(name, \"tier\")}-flag` : undefined\n\n  return (\n    <Root\n      className={cn(\n        \"bg-card text-card-foreground relative flex h-full flex-col gap-6 rounded-xl border p-6 sm:p-8\",\n        featured && \"border-primary ring-primary shadow-lg ring-1\",\n        className,\n      )}\n    >\n      <div className=\"flex flex-col gap-2\">\n        <div className=\"flex items-center justify-between gap-3\">\n          <Heading level={headingLevel} className=\"text-foreground text-lg font-semibold\">\n            {name}\n          </Heading>\n          {featured ? (\n            <Badge id={flagId} variant=\"primary\" size=\"sm\">\n              {featuredLabel}\n            </Badge>\n          ) : null}\n        </div>\n        {description ? (\n          <p className=\"text-muted-foreground text-pretty text-sm\">{description}</p>\n        ) : null}\n      </div>\n\n      <p className=\"flex items-baseline gap-1\">\n        <span\n          aria-hidden\n          className=\"text-foreground text-display-sm font-semibold tracking-tight\"\n        >\n          {price}\n        </span>\n        {period ? (\n          <span aria-hidden className=\"text-muted-foreground text-sm\">\n            {period}\n          </span>\n        ) : null}\n        <span className=\"sr-only\">\n          {srPrice ?? price}\n          {period ? ` ${period.replace(/^\\//, \"per \")}` : \"\"}\n        </span>\n      </p>\n\n      <ul className=\"flex flex-1 flex-col gap-3\">\n        {features.map((feature) => {\n          const included = feature.included ?? true\n          const Icon = included ? CheckIcon : XIcon\n          return (\n            <li key={feature.label} className=\"flex items-start gap-3 text-sm\">\n              <Icon\n                aria-hidden\n                focusable=\"false\"\n                className={cn(\n                  \"mt-0.5 size-4 shrink-0\",\n                  included ? \"text-primary\" : \"text-muted-foreground\",\n                )}\n              />\n              <span\n                className={cn(\n                  \"flex flex-col gap-0.5\",\n                  !included && \"text-muted-foreground\",\n                )}\n              >\n                <span className={cn(!included && \"line-through\")}>\n                  <span className=\"sr-only\">\n                    {included ? \"Included: \" : \"Not included: \"}\n                  </span>\n                  {feature.label}\n                </span>\n                {feature.note ? (\n                  <span className=\"text-muted-foreground text-xs\">{feature.note}</span>\n                ) : null}\n              </span>\n            </li>\n          )\n        })}\n      </ul>\n\n      {children}\n\n      <div className=\"flex flex-col gap-2\">\n        <Link\n          href={cta.href}\n          aria-describedby={flagId}\n          aria-label={cta[\"aria-label\"] ?? `${cta.label} — ${name}`}\n          {...(cta.external ? { target: \"_blank\", rel: \"noopener noreferrer\" } : {})}\n          className={cn(\n            buttonVariants({\n              variant: cta.variant ?? (featured ? \"primary\" : \"outline\"),\n              size: \"md\",\n              fullWidth: true,\n            }),\n          )}\n        >\n          {cta.label}\n        </Link>\n        {footnote ? (\n          <p className=\"text-muted-foreground text-pretty text-center text-xs\">\n            {footnote}\n          </p>\n        ) : null}\n      </div>\n    </Root>\n  )\n}\n"
    }
  ],
  "docs": "Import styles/facade-tokens.css in your global stylesheet, after @import \"tailwindcss\". Docs: https://facadeui.dev/components/pricing-tier"
}
