{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pricing-card",
  "title": "Pricing Card",
  "description": "A single pricing plan card — the tier box on a pricing page, a plans-and-billing settings screen, an upgrade or paywall modal, a compare-plans table, or the subscription row in an account page. It takes a plan name, a big price with its billing period ($29 /mo), an optional one-line pitch, a feature list and a call-to-action, and several of them sit side by side to make the whole pricing table. Features are the part that is usually got wrong. Pass a string for an included feature or an object to mark one excluded; an excluded row is muted and struck through, and it also carries a screen-reader-only \"Not included:\" prefix — because text-decoration: line-through is not announced, so a purely visual strikethrough tells a sighted reader the feature is missing and tells a screen-reader user it is included. The check and minus icons are aria-hidden, since the text already says which is which. Set featured to mark the recommended tier: it draws a primary ring and a \"Most popular\" badge, and badge takes any other label (Best value, Current plan). headingLevel picks h2, h3 or h4 so three cards dropped into a section do not break the page outline — a pricing table is the classic place where a hardcoded h3 lands under the wrong h2. Against official shadcn/ui there is no pricing card to compare with, only pieces to assemble: card is a 1,828-character generic container with no price, plan, tier or feature vocabulary in it at all, item is a ten-part compound kit (ItemGroup, Item, ItemMedia, ItemContent, ItemTitle, ItemDescription, ItemActions, ItemHeader, ItemFooter, ItemSeparator) that additionally pulls in separator and is built for list rows, and badge and button each drag in @radix-ui/react-slot. None of the four contains a single pricing term. This is one component with lucide-react as its only dependency, theme-aware through shadcn tokens in light and dark.",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/ui/pricing-card.tsx",
      "content": "import * as React from \"react\"\nimport { Check, Minus } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/**\n * A single plan feature. Pass a string for an included feature, or an object to\n * mark it excluded (rendered muted with a strikethrough and an accessible\n * \"not included\" label).\n */\nexport type PricingFeature = string | { text: string; included?: boolean }\n\ninterface PricingCardProps\n  extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"title\"> {\n  /** Plan name, e.g. \"Pro\". Rendered as the card heading. */\n  name: string\n  /** The price, e.g. \"$29\" or a custom node. Kept flexible for \"Free\"/\"Custom\". */\n  price: React.ReactNode\n  /** Billing period shown next to the price, e.g. \"/mo\". */\n  period?: string\n  /** Short plan description under the name. */\n  description?: string\n  /** Feature list. Strings are included; objects can be marked excluded. */\n  features?: PricingFeature[]\n  /** Call-to-action, usually a link or button rendered under the features. */\n  cta?: React.ReactNode\n  /**\n   * Highlight this plan: adds a primary ring and shows a badge. Use for the\n   * recommended tier in a pricing row.\n   */\n  featured?: boolean\n  /** Badge content shown when `featured` (or whenever provided). Defaults to \"Most popular\". */\n  badge?: React.ReactNode\n  /** Accessible heading level for the plan name. Defaults to `h3`. */\n  headingLevel?: \"h2\" | \"h3\" | \"h4\"\n}\n\nfunction normalize(feature: PricingFeature): { text: string; included: boolean } {\n  return typeof feature === \"string\"\n    ? { text: feature, included: true }\n    : { text: feature.text, included: feature.included !== false }\n}\n\n/**\n * A pricing plan card: plan name, price with billing period, an optional\n * description, a checked/unchecked feature list, and a call-to-action. Set\n * `featured` to highlight the recommended tier with a ring and a badge. Compose\n * several side by side for a pricing page or upsell/paywall row. shadcn/ui ships\n * no pricing card. Theme-aware via shadcn tokens with dark mode.\n */\nexport function PricingCard({\n  name,\n  price,\n  period,\n  description,\n  features,\n  cta,\n  featured = false,\n  badge,\n  headingLevel = \"h3\",\n  className,\n  ...props\n}: PricingCardProps) {\n  const Heading = headingLevel\n  const badgeContent = badge ?? (featured ? \"Most popular\" : null)\n\n  return (\n    <div\n      className={cn(\n        \"relative flex flex-col rounded-lg border bg-card p-6 text-card-foreground\",\n        featured && \"border-primary ring-1 ring-primary\",\n        className\n      )}\n      {...props}\n    >\n      {badgeContent ? (\n        <span className=\"absolute -top-3 left-6 inline-flex items-center rounded-full bg-primary px-3 py-0.5 text-xs font-medium text-primary-foreground\">\n          {badgeContent}\n        </span>\n      ) : null}\n\n      <Heading className=\"text-lg font-semibold tracking-tight\">{name}</Heading>\n      {description ? (\n        <p className=\"mt-1 text-sm text-muted-foreground\">{description}</p>\n      ) : null}\n\n      <div className=\"mt-4 flex items-baseline gap-1\">\n        <span className=\"text-3xl font-semibold tracking-tight\">{price}</span>\n        {period ? (\n          <span className=\"text-sm text-muted-foreground\">{period}</span>\n        ) : null}\n      </div>\n\n      {features && features.length > 0 ? (\n        <ul className=\"mt-6 flex-1 space-y-3 text-sm\">\n          {features.map((feature, i) => {\n            const { text, included } = normalize(feature)\n            return (\n              <li key={i} className=\"flex items-start gap-2\">\n                {included ? (\n                  <Check\n                    className=\"mt-0.5 h-4 w-4 shrink-0 text-primary\"\n                    aria-hidden=\"true\"\n                  />\n                ) : (\n                  <Minus\n                    className=\"mt-0.5 h-4 w-4 shrink-0 text-muted-foreground\"\n                    aria-hidden=\"true\"\n                  />\n                )}\n                <span className={cn(!included && \"text-muted-foreground line-through\")}>\n                  {!included ? <span className=\"sr-only\">Not included: </span> : null}\n                  {text}\n                </span>\n              </li>\n            )\n          })}\n        </ul>\n      ) : null}\n\n      {cta ? <div className=\"mt-6\">{cta}</div> : null}\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}