{ "name": "pricing-card-one", "type": "registry:ui", "registryDependencies": [], "dependencies": [], "devDependencies": [], "tailwind": {}, "cssVars": { "light": {}, "dark": {} }, "files": [ { "path": "pricing-card-one.tsx", "content": "'use client';\n\nimport * as React from 'react';\nimport { cn } from '@/lib/utils';\n\ntype AnchorOrButton =\n | ({\n href: string;\n onClick?: never;\n } & React.AnchorHTMLAttributes)\n | ({\n href?: undefined;\n onClick?: React.MouseEventHandler;\n } & React.ButtonHTMLAttributes);\n\ntype Tone = 'indigo' | 'blue' | 'emerald' | 'zinc';\ntype Variant = 'outline' | 'elevated' | 'soft';\n\nexport type PricingFeature = {\n label: React.ReactNode;\n included?: boolean; // default true\n};\n\nexport type PricingCardOneProps = {\n icon?: React.ReactNode; // big top icon\n name: string; // plan name\n subtitle?: string; // \"the starter choice\"\n price: number | string; // 5 | \"$5\"\n currency?: string; // \"$\" (used when price is number)\n periodLabel?: string; // \"/month\"\n recommended?: boolean;\n recommendedLabel?: string;\n\n features: PricingFeature[];\n\n /** CTA button/link. If omitted, no button is shown. */\n cta?: AnchorOrButton & { label?: string; 'aria-label'?: string };\n\n /** Visuals */\n tone?: Tone;\n variant?: Variant;\n className?: string;\n\n /** Slot style overrides */\n badgeClassName?: string;\n iconClassName?: string;\n nameClassName?: string;\n subtitleClassName?: string;\n priceClassName?: string;\n periodClassName?: string;\n featureListClassName?: string;\n featureItemClassName?: string;\n ctaClassName?: string;\n};\n\nconst toneMap: Record<\n Tone,\n {\n accent: string; // text color for icon/price\n ring: string; // ring color for included bullet\n bulletOkBg: string; // bg for ✓\n bulletOkFg: string;\n bulletNoBg: string; // bg for ✕\n bulletNoFg: string;\n primaryBtn: string; // filled button\n primaryBtnHover: string;\n outlineBtn: string; // outline button text/ring\n }\n> = {\n indigo: {\n accent: 'text-indigo-600',\n ring: 'ring-indigo-200 dark:ring-indigo-900/50',\n bulletOkBg: 'bg-indigo-50 dark:bg-indigo-950/40',\n bulletOkFg: 'text-indigo-600 dark:text-indigo-400',\n bulletNoBg: 'bg-amber-50 dark:bg-amber-950/40',\n bulletNoFg: 'text-amber-500',\n primaryBtn: 'bg-indigo-600 text-white',\n primaryBtnHover: 'hover:bg-indigo-700',\n outlineBtn:\n 'text-indigo-600 ring-1 ring-inset ring-indigo-200 dark:ring-indigo-900/50',\n },\n blue: {\n accent: 'text-blue-600',\n ring: 'ring-blue-200 dark:ring-blue-900/50',\n bulletOkBg: 'bg-blue-50 dark:bg-blue-950/40',\n bulletOkFg: 'text-blue-600 dark:text-blue-400',\n bulletNoBg: 'bg-amber-50 dark:bg-amber-950/40',\n bulletNoFg: 'text-amber-500',\n primaryBtn: 'bg-blue-600 text-white',\n primaryBtnHover: 'hover:bg-blue-700',\n outlineBtn:\n 'text-blue-600 ring-1 ring-inset ring-blue-200 dark:ring-blue-900/50',\n },\n emerald: {\n accent: 'text-emerald-600',\n ring: 'ring-emerald-200 dark:ring-emerald-900/50',\n bulletOkBg: 'bg-emerald-50 dark:bg-emerald-950/40',\n bulletOkFg: 'text-emerald-600 dark:text-emerald-400',\n bulletNoBg: 'bg-amber-50 dark:bg-amber-950/40',\n bulletNoFg: 'text-amber-500',\n primaryBtn: 'bg-emerald-600 text-white',\n primaryBtnHover: 'hover:bg-emerald-700',\n outlineBtn:\n 'text-emerald-600 ring-1 ring-inset ring-emerald-200 dark:ring-emerald-900/50',\n },\n zinc: {\n accent: 'text-zinc-900 dark:text-zinc-50',\n ring: 'ring-zinc-200 dark:ring-zinc-800',\n bulletOkBg: 'bg-zinc-100 dark:bg-zinc-800/60',\n bulletOkFg: 'text-zinc-700 dark:text-zinc-300',\n bulletNoBg: 'bg-amber-50 dark:bg-amber-950/40',\n bulletNoFg: 'text-amber-500',\n primaryBtn: 'bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900',\n primaryBtnHover: 'hover:bg-black/80 dark:hover:bg-white',\n outlineBtn:\n 'text-zinc-700 ring-1 ring-inset ring-zinc-200 dark:text-zinc-300 dark:ring-zinc-800',\n },\n};\n\nexport default function PricingCardOne({\n icon,\n name,\n subtitle = 'the starter choice',\n price,\n currency = '$',\n periodLabel = '/month',\n recommended = false,\n recommendedLabel = 'Recommended',\n features,\n cta,\n tone = 'blue',\n variant = 'outline',\n className,\n badgeClassName,\n iconClassName,\n nameClassName,\n subtitleClassName,\n priceClassName,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n periodClassName,\n featureListClassName,\n featureItemClassName,\n ctaClassName,\n}: PricingCardOneProps) {\n const t = toneMap[tone];\n\n const shell =\n variant === 'elevated'\n ? 'bg-white dark:bg-zinc-950 shadow-sm ring-1 ring-zinc-200 dark:ring-zinc-800'\n : variant === 'soft'\n ? 'bg-white/70 dark:bg-zinc-900/60 ring-1 ring-zinc-200 dark:ring-zinc-800'\n : 'bg-white dark:bg-zinc-950 ring-1 ring-zinc-200 dark:ring-zinc-800';\n\n const priceText =\n typeof price === 'number' ? (\n <>\n \n {currency}\n {price}\n \n \n {periodLabel}\n \n \n ) : (\n <>\n {price}\n \n {periodLabel}\n \n \n );\n\n return (\n \n {/* Recommended badge */}\n {recommended && (\n \n {recommendedLabel}\n \n )}\n\n {/* Icon */}\n {icon && (\n \n {icon}\n \n )}\n\n {/* Heading */}\n \n {name}\n \n {subtitle && (\n \n {subtitle}\n

\n )}\n\n {/* Price */}\n
{priceText}
\n\n {/* Features */}\n
    \n {features.map((f, i) => {\n const ok = f.included !== false;\n return (\n \n \n {ok ? (\n \n \n \n ) : (\n \n \n \n )}\n \n \n {f.label}\n \n \n );\n })}\n
\n\n {/* CTA */}\n {cta && (\n <>\n {cta.href ? (\n \n {cta.label ?? 'Choose Plan'}\n \n ) : (\n \n {cta.label ?? 'Choose Plan'}\n \n )}\n \n )}\n \n );\n}\n", "type": "registry:ui" } ] }