# Pricing 07

> A simple pricing block

A shadcn/ui block from the [@shadcnui-blocks](https://shadcnui-blocks.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/shadcnui-blocks/pricing-07).

- Page, with a live preview: https://shadcn.exchange/r/shadcnui-blocks/pricing-07
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/shadcnui-blocks/pricing-07-light-1b25abd6322e1aa3.png
- Registry item: https://shadcnui-blocks.com/r/pricing-07.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcnui-blocks.com/r/pricing-07.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `@number-flow/react`

## Files

### `src/registry/blocks/radix/pricing-07/components/pricing.tsx`

```tsx
"use client";

import NumberFlow from "@number-flow/react";
import { Box, CircleCheck, Gem, type LucideIcon, Users } from "lucide-react";
import { useState } from "react";
import { cn } from "@/lib/utils";
import { Badge } from "@/registry/bases/radix/ui/badge";
import { Button } from "@/registry/bases/radix/ui/button";
import { Tabs, TabsList, TabsTrigger } from "@/registry/bases/radix/ui/tabs";

interface PricingPlan {
  name: string;
  description: string;
  price: number;
  isRecommended: boolean;
  icon: LucideIcon;
  features: string[];
}
type BillingPeriod = "monthly" | "yearly";

const pricingPlans: PricingPlan[] = [
  {
    name: "Basic",
    description: "Perfect for individuals getting started.",
    price: 0,
    isRecommended: false,
    icon: Box,
    features: [
      "1 Project",
      "Community Support",
      "Basic Analytics",
      "Limited Components",
    ],
  },
  {
    name: "Pro",
    description: "Ideal for professionals who need more power.",
    price: 19,
    isRecommended: true,
    icon: Gem,
    features: [
      "Unlimited Projects",
      "Priority Support",
      "Advanced Analytics",
      "Access to Premium Components",
      "Custom Branding",
    ],
  },
  {
    name: "Team",
    description: "Best for growing teams and small businesses.",
    price: 49,
    isRecommended: false,
    icon: Users,
    features: [
      "Everything in Pro",
      "Team Collaboration",
      "Role-based Access",
      "Usage Insights",
      "Dedicated Support",
    ],
  },
];

const YEARLY_DISCOUNT_PERCENTAGE = 20;

const Pricing = () => {
  const [billingPeriod, setBillingPeriod] = useState<BillingPeriod>("yearly");

  const handleBillingPeriodChange = (value: string) => {
    setBillingPeriod(value as BillingPeriod);
  };

  return (
    <section className="mx-auto flex max-w-6xl flex-col gap-12 px-6 py-16">
      <Tabs
        className="mx-auto"
        defaultValue="yearly"
        onValueChange={handleBillingPeriodChange}
        value={billingPeriod}
      >
        <TabsList>
          <TabsTrigger className="px-4" value="monthly">
            Monthly
          </TabsTrigger>
          <TabsTrigger className="px-4" value="yearly">
            Yearly
          </TabsTrigger>
        </TabsList>
      </Tabs>

      <div className="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-2 md:grid-cols-3">
        {pricingPlans.map((plan) => (
          <PlanCard billingPeriod={billingPeriod} key={plan.name} plan={plan} />
        ))}
      </div>
    </section>
  );
};

const PlanCard = ({
  plan,
  billingPeriod,
}: {
  plan: PricingPlan;
  billingPeriod: BillingPeriod;
}) => {
  const price =
    billingPeriod === "yearly"
      ? Math.floor((plan.price * (100 - YEARLY_DISCOUNT_PERCENTAGE)) / 100)
      : plan.price;

  return (
    <div
      className={cn("rounded-lg bg-card p-6 shadow-xs/3 ring ring-border/85", {
        "relative bg-primary/5 ring-2 ring-primary": plan.isRecommended,
      })}
    >
      {plan.isRecommended && (
        <Badge className="absolute -top-3 left-1/2 -translate-x-1/2">
          Most Popular
        </Badge>
      )}
      <plan.icon className="mb-4 text-primary" />
      <div className="flex items-center gap-1">
        <h3 className="font-medium text-2xl tracking-tight">{plan.name}</h3>
      </div>
      <p className="mt-2 min-h-[2lh] text-muted-foreground">
        {plan.description}
      </p>
      <p className="mt-4 font-semibold text-4xl">
        <NumberFlow className="font-satoshi" prefix="$" value={price} />
        <span className="ms-0.5 font-normal text-lg text-muted-foreground tracking-tight">
          /month
        </span>
      </p>
      <Button className="mt-6 mb-8 h-10 w-full" size="lg">
        Get Started
      </Button>
      <ul className="space-y-2">
        {plan.features.map((feature) => (
          <li className="flex items-center gap-2" key={feature}>
            <CircleCheck className="size-4 shrink-0 text-primary" />
            {feature}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default Pricing;
```
