Hazine

Pricing Table

A responsive pricing grid with highlighted tier and feature lists.

Free
All core components, MIT licensed.
$0
  • All components
  • CLI + MCP access
  • Community Discord
Pro
Popular
Every block and template, forever.
$149lifetime
  • All pro blocks
  • All templates
  • All future drops
  • Commercial use
Team
Your whole team, one license.
$399lifetime · 10 seats
  • Everything in Pro
  • 10 seats
  • Org-wide access

Installation

npx shadcn@latest add @hazine/pricing-table

Source

import * as React from "react"
import { CheckIcon } from "lucide-react"

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

export interface PricingTier {
  name: string
  price: string
  priceNote?: string
  description: string
  features: string[]
  action: { label: string; href: string }
  highlighted?: boolean
  badge?: string
}

interface PricingTableProps extends React.ComponentProps<"div"> {
  tiers: PricingTier[]
}

export function PricingTable({ tiers, className, ...props }: PricingTableProps) {
  return (
    <div
      className={cn(
        "grid gap-6 sm:grid-cols-2 lg:grid-cols-3",
        className
      )}
      {...props}
    >
      {tiers.map((tier) => (
        <Card
          key={tier.name}
          className={cn(
            "flex flex-col",
            tier.highlighted && "border-primary shadow-md"
          )}
        >
          <CardHeader>
            <div className="flex items-center justify-between">
              <CardTitle>{tier.name}</CardTitle>
              {tier.badge && <Badge>{tier.badge}</Badge>}
            </div>
            <CardDescription>{tier.description}</CardDescription>
          </CardHeader>
          <CardContent className="flex flex-1 flex-col gap-6">
            <div className="flex items-baseline gap-1.5">
              <span className="text-4xl font-semibold tracking-tight">
                {tier.price}
              </span>
              {tier.priceNote && (
                <span className="text-sm text-muted-foreground">
                  {tier.priceNote}
                </span>
              )}
            </div>
            <ul className="flex flex-col gap-2.5 text-sm">
              {tier.features.map((feature) => (
                <li key={feature} className="flex items-start gap-2">
                  <CheckIcon className="mt-0.5 size-4 shrink-0 text-primary" />
                  {feature}
                </li>
              ))}
            </ul>
          </CardContent>
          <CardFooter>
            <Button
              className="w-full"
              variant={tier.highlighted ? "default" : "outline"}
              asChild
            >
              <a href={tier.action.href}>{tier.action.label}</a>
            </Button>
          </CardFooter>
        </Card>
      ))}
    </div>
  )
}

Dependencies