Skip to content
6

Pricing 1

Three-tier card row with a featured middle plan. Each card lists price, blurb, feature checklist and a primary or outline CTA.

Preview

Installation

npx shadcn@latest add https://hirael.com/r/pricing-01.json

Code

components/blocks/pricing-01.tsx
'use client';

import * as React from 'react';
import { Check } from 'lucide-react';

import { Button } from '@/registry/hirael/bases/radix/ui/button';
import { Card, CardContent, CardFooter, CardHeader } from '@/registry/hirael/bases/radix/ui/card';
import { Separator } from '@/registry/hirael/bases/radix/ui/separator';
import { cn } from '@/lib/utils';

interface Tier {
  name: string;
  price: string;
  blurb: string;
  features: readonly string[];
  cta: string;
  featured?: boolean;
  ctaVariant: 'default' | 'outline';
}

const TIERS: readonly Tier[] = [
  {
    name: 'Hobby',
    price: '$0',
    blurb: 'For weekend projects and solo prototypes.',
    features: ['Full registry access', 'Up to 3 themes', 'Community support', 'Full source access'],
    cta: 'Start free',
    ctaVariant: 'outline',
  },
  {
    name: 'Pro',
    price: '$18',
    blurb: 'For shipping real products with real users.',
    features: ['Everything in Hobby', 'Unlimited themes', 'Private registry mirror', 'Priority response'],
    cta: 'Start Pro trial',
    featured: true,
    ctaVariant: 'default',
  },
  {
    name: 'Team',
    price: '$48',
    blurb: 'For studios and product teams shipping side-by-side.',
    features: ['Everything in Pro', 'Shared workspace', 'SSO & audit log', 'SLA support'],
    cta: 'Contact sales',
    ctaVariant: 'outline',
  },
];

const Pricing01 = () => {
  return (
    <section className="bg-background py-20 sm:py-28">
      <div className="container w-full">
        <div className="mx-auto flex max-w-2xl flex-col items-center gap-5 text-center">
          <span className="inline-flex items-center gap-2 font-mono text-[10px] uppercase tracking-[0.14em] text-foreground">
            <span className="size-1 rounded-full bg-foreground" />
            Pricing
          </span>
          <h2 className="font-serif text-4xl font-medium leading-[1.04] tracking-tight sm:text-5xl">
            Pay for the parts you <span className="italic text-foreground">actually</span> use.
          </h2>
          <p className="text-base text-muted-foreground sm:text-lg">
            Source code stays free. Pay only when you need private mirrors, shared themes, or team-level controls.
          </p>
        </div>

        <div className="mt-14 grid grid-cols-1 gap-4 md:grid-cols-3">
          {TIERS.map((tier) => (
            <Card
              key={tier.name}
              style={
                tier.featured
                  ? {
                      backgroundImage:
                        'radial-gradient(120% 90% at 50% 0%, color-mix(in oklch, var(--primary) 9%, transparent), transparent 60%)',
                    }
                  : undefined
              }
              className={cn(
                'relative gap-6 rounded-xl p-6 transition-all duration-200 hover:-translate-y-1',
                tier.featured ? 'ring-1 ring-foreground/25' : 'hover:border-foreground/20',
              )}
            >
              {tier.featured && (
                <span className="absolute -top-2.5 end-6 inline-flex items-center rounded-full border border-border bg-background px-2.5 py-0.5 font-mono text-[10px] uppercase tracking-[0.12em] text-foreground">
                  Most popular
                </span>
              )}

              <CardHeader className="flex flex-col gap-2 px-0">
                <span className="font-mono text-[10px] uppercase tracking-[0.12em] text-muted-foreground">
                  {tier.name}
                </span>
                <div className="flex items-baseline gap-1">
                  <span className="text-4xl font-semibold tracking-[-0.04em]">{tier.price}</span>
                  <span className="font-mono text-xs text-muted-foreground">/mo</span>
                </div>
                <p className="text-sm text-muted-foreground">{tier.blurb}</p>
              </CardHeader>

              <Separator className="border-dashed" />

              <CardContent className="px-0">
                <ul className="flex flex-col gap-2.5">
                  {tier.features.map((f) => (
                    <li key={f} className="flex items-start gap-2.5 text-sm text-foreground">
                      <Check className="mt-0.5 size-4 shrink-0 text-foreground" />
                      {f}
                    </li>
                  ))}
                </ul>
              </CardContent>

              <CardFooter className="mt-auto px-0 pt-2">
                <Button asChild variant={tier.ctaVariant} size="lg" className="w-full rounded-full">
                  <a href="#">{tier.cta}</a>
                </Button>
              </CardFooter>
            </Card>
          ))}
        </div>
      </div>
    </section>
  );
};

export default Pricing01;

Dependencies

shadcn registry

buttoncardseparator

npm

lucide-react