# Pricing Section

> Plans, billing periods, limits, and purchase actions in one section.

- Category: Marketing
- Kind: block
- Page: https://uaiblocks.dev/components/pricing-section
- Registry item: https://uaiblocks.dev/r/pricing-section.json
- Source: https://github.com/victor-teles/uai/blob/main/src/registry/uai/blocks/pricing-section.tsx

## Install

```bash
bunx shadcn@latest add https://uaiblocks.dev/r/pricing-section.json
```

## Usage

```tsx
"use client";

import { useState } from "react";
import {
  PricingSection,
  PricingSectionDescription,
  PricingSectionFootnote,
  PricingSectionHeader,
  PricingSectionPlan,
  PricingSectionPlanAction,
  PricingSectionPlanBadge,
  PricingSectionPlanDescription,
  PricingSectionPlanFeature,
  PricingSectionPlanFeatures,
  PricingSectionPlanName,
  PricingSectionPlanPeriod,
  PricingSectionPlanPrice,
  PricingSectionPlans,
  PricingSectionTitle,
  type PricingSectionVariant,
} from "@/components/uai/pricing-section";
import {
  PricingToggleList,
  PricingToggleOption,
  PricingTogglePrice,
  PricingToggleSavings,
} from "@/components/ui/uai/pricing-toggle";

const plans = [
  {
    name: "Crew",
    monthly: 18,
    yearly: 15,
    note: "For one team answering its own requests.",
    features: [
      { label: "Up to 5 seats", included: true },
      { label: "2 shared inboxes", included: true },
      { label: "Text arrival updates", included: true },
      { label: "Routing rules", included: false },
    ],
  },
  {
    name: "Operations",
    monthly: 32,
    yearly: 26,
    note: "For dispatchers coordinating several crews.",
    featured: true,
    features: [
      { label: "Up to 50 seats", included: true },
      { label: "Unlimited inboxes", included: true },
      { label: "Routing rules and travel-time scheduling", included: true },
      { label: "Single sign-on", included: false },
    ],
  },
  {
    name: "Enterprise",
    monthly: 54,
    yearly: 45,
    note: "For regional companies with audit needs.",
    features: [
      { label: "Unlimited seats", included: true },
      { label: "Single sign-on and SCIM", included: true },
      { label: "Audit log retention for 2 years", included: true },
      { label: "Named support manager", included: true },
    ],
  },
];

export function PricingSectionPreview({ variant = "cards" }: { variant?: PricingSectionVariant }) {
  const [period, setPeriod] = useState("yearly");
  return (
    <PricingSection variant={variant} value={period} onValueChange={setPeriod}>
      <PricingSectionHeader>
        <PricingSectionTitle>Pay for the crews you dispatch</PricingSectionTitle>
        <PricingSectionDescription>
          Every plan includes the shared inbox and customer updates. Change plans at any time.
        </PricingSectionDescription>
        <PricingToggleList aria-label="Billing period">
          <PricingToggleOption value="monthly">Monthly</PricingToggleOption>
          <PricingToggleOption value="yearly">
            Yearly <PricingToggleSavings>Save 18%</PricingToggleSavings>
          </PricingToggleOption>
        </PricingToggleList>
      </PricingSectionHeader>
      <PricingSectionPlans>
        {plans.map((plan) => (
          <PricingSectionPlan key={plan.name} featured={plan.featured}>
            <PricingSectionPlanName>
              {plan.name}
              {plan.featured ? (
                <PricingSectionPlanBadge>Most popular</PricingSectionPlanBadge>
              ) : null}
            </PricingSectionPlanName>
            <PricingSectionPlanPrice>
              <PricingTogglePrice period="monthly">${plan.monthly}</PricingTogglePrice>
              <PricingTogglePrice period="yearly">${plan.yearly}</PricingTogglePrice>
              <PricingSectionPlanPeriod>per seat / month</PricingSectionPlanPeriod>
            </PricingSectionPlanPrice>
            <PricingSectionPlanDescription>{plan.note}</PricingSectionPlanDescription>
            <PricingSectionPlanFeatures>
              {plan.features.map((feature) => (
                <PricingSectionPlanFeature key={feature.label} included={feature.included}>
                  {feature.label}
                </PricingSectionPlanFeature>
              ))}
            </PricingSectionPlanFeatures>
            <PricingSectionPlanAction href={`#checkout-${plan.name.toLowerCase()}`}>
              {plan.name === "Enterprise" ? "Talk to sales" : `Choose ${plan.name}`}
            </PricingSectionPlanAction>
          </PricingSectionPlan>
        ))}
      </PricingSectionPlans>
      <PricingSectionFootnote>
        Prices in US dollars, before tax. Yearly plans are billed once and renew annually.
      </PricingSectionFootnote>
    </PricingSection>
  );
}
```

## Anatomy

- `PricingSection`
  - `PricingSectionHeader`
    - `PricingSectionTitle`
    - `PricingSectionDescription`
    - `PricingToggleList`
      - `PricingToggleOption`
  - `PricingSectionPlans`
    - `PricingSectionPlan`
      - `PricingSectionPlanName`
        - `PricingSectionPlanBadge`
      - `PricingSectionPlanPrice`
        - `PricingTogglePrice`
        - `PricingSectionPlanPeriod`
      - `PricingSectionPlanDescription`
      - `PricingSectionPlanFeatures`
        - `PricingSectionPlanFeature`
      - `PricingSectionPlanAction`
  - `PricingSectionFootnote`

## Accessibility

- The billing period is an APG radio group from Pricing Toggle with arrow, Home, and End keys.
- Each plan is a list item named by its plan heading; the featured plan also says so in text.
- Excluded limits use a minus icon plus hidden “Not included” text, so they never depend on the icon.
