Back to components
Commerce

Pricing Card

A reusable plan card with feature highlights and a primary action.

Page preview
Source
This is the component source that shadcn installs into a consuming project.
registry/default/pricing-card/pricing-card.tsx
import { CheckIcon, SparklesIcon } from "lucide-react"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import { Separator } from "@/components/ui/separator"

type PricingCardCopy = {
  badge: string
  plan: string
  description: string
  price: string
  period: string
  action: string
  features: [string, string, string]
}

type PricingCardProps = {
  copy?: PricingCardCopy
}

const defaultCopy: PricingCardCopy = {
  badge: "Popular",
  plan: "Team",
  description: "For small product teams that need shared UI blocks.",
  price: "$29",
  period: "per seat / month",
  action: "Start trial",
  features: ["Registry installs", "Preview workspace", "Shared component notes"],
}

export function PricingCard({ copy = defaultCopy }: PricingCardProps) {
  return (
    <Card className="w-full max-w-sm">
      <CardHeader>
        <div className="flex flex-wrap items-start justify-between gap-3">
          <div className="flex min-w-0 flex-col gap-1">
            <CardTitle>{copy.plan}</CardTitle>
            <CardDescription>{copy.description}</CardDescription>
          </div>
          <Badge variant="secondary">{copy.badge}</Badge>
        </div>
      </CardHeader>
      <CardContent className="flex flex-col gap-5">
        <div className="flex items-end gap-2">
          <span className="text-4xl font-semibold tracking-tight">
            {copy.price}
          </span>
          <span className="pb-1 text-sm text-muted-foreground">
            {copy.period}
          </span>
        </div>
        <Separator />
        <ul className="flex flex-col gap-3 text-sm">
          {copy.features.map((feature) => (
            <li key={feature} className="flex gap-2">
              <CheckIcon className="mt-0.5" />
              <span>{feature}</span>
            </li>
          ))}
        </ul>
      </CardContent>
      <CardFooter>
        <Button className="w-full">
          <SparklesIcon data-icon="inline-start" />
          {copy.action}
        </Button>
      </CardFooter>
    </Card>
  )
}