# Pricing Cards (Moonarc)

Shows pricing plans side by side, with an annual/monthly toggle that swaps every price with zero JavaScript (radios and :has), the highlighted plan wearing a travelling border beam, cards revealed with a stagger. Plans with no monthly price render without the toggle.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/pricing-cards` (license key required)
- Tier B · category section · trigger scroll, click
- Readout: `<PricingCards plans={[…]}>`
- Browser support: newly (Chrome 105 · Firefox 128 · Safari 16.4); elsewhere: a static ring on the highlighted plan
- Measured cost: 0 B JS of its own · uses Reveal + runtime (with dependencies 3.0 kB raw; CSS 13.1 kB raw)
- Page: https://moonarc.dev/components/pricing-cards/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `plans` | `{ name, monthly?, annual, blurb?, features, action, highlight? }[]` | none | Plans; one can be highlighted. Leave out `monthly` on every plan for yearly-only pricing: the toggle is not rendered and each card shows its yearly price. |
| `currency` | `string` | `'$'` | Currency symbol. |
| `priceFormat` | `string` | `'{currency}{n}'` | How a price prints: {currency} is the currency prop and {n} the amount, so '{n} {currency}' puts the symbol after it. |
| `locale` | `string` | `unset (the number as given)` | Intl locale of the amount: its thousands separator and digits. |
| `perYear` | `string` | `'/yr'` | The small text after the yearly price. |
| `perMonth` | `string` | `'/mo'` | The small text after the monthly price. |
| `annualLabel` | `string` | `'Annual'` | The toggle's yearly choice. |
| `monthlyLabel` | `string` | `'Monthly'` | The toggle's monthly choice. |
| `billingLabel` | `string` | `'Billing period'` | Accessible name of the toggle's group. |
| `id` | `string` | `'ma-pricing'` | Radio group prefix; unique per page. |
| `tone` | `'surface' | 'muted' | 'ink' | 'brand'` | `unset (paints nothing)` | The ground: the page surface, a muted band, an always-dark ink panel, or a deep brand panel. Each paints --background, --ma-tone-muted (over --muted, with a --border hairline), --ma-tone-ink or --ma-tone-brand (over --primary) with the matching text. With theme.css, a painted tone also re-declares --card, --border, --input and --ring inside the section, so cards and fields follow the ground. Decoration is strongest on brand. |
| `density` | `'compact' | 'cozy' | 'roomy'` | `'cozy'` | Card padding and gaps ×0.8 / ×1 / ×1.25 through --ma-density. |

## Usage

```astro
---
import PricingCards from '@/components/moonarc/pro/PricingCards.astro';
---
<PricingCards plans={[
  { name: 'Starter', monthly: 0, annual: 0, features: ['3 projects', 'Community support'], action: { href: '/signup/', label: 'Start' } },
  { name: 'Plus', monthly: 12, annual: 120, features: ['Unlimited projects', 'Priority support'], action: { href: '/checkout/', label: 'Subscribe' }, highlight: true },
]} />
```

## Reduced motion

Cards fade in without stagger; the beam stops.

## With ClientRouter

Inherits Reveal and BorderBeam; the toggle is a radio and resets with the page.

## Craft

- The billing toggle is two radios: the price swap is display on two spans, no state, no script.
- Only the highlighted plan gets the beam, so it stays the one card that stands out.
- Stagger 80 ms: three cards land inside a quarter second, left to right, the order you read prices.

## Replaces

- Pricing sections (Tailwind Plus)
- Pricing (shadcnblocks)

## Source

Pro block. The source is served by the license-gated registry: `npx shadcn@latest add @moonarc-pro/pricing-cards` with a key in components.json (https://moonarc.dev/account/). Everything it composes is free: reveal, border-beam.
