# Simple pricing grid

> Compare plans side by side and highlight a recommended choice. Each card links to your signup, checkout or contact page.

- ID: `cmp_pricing_grid_001`
- Slug: `pricing-grid-01`
- Version: `1.0.0` (current)
- Status: published
- Published: 2026-09-16
- Updated: 2026-09-17
- Available versions: `1.0.0`
- Kind: section
- Primary category: `pricing`
- Detail page: https://pagesugar.com/components/pricing-grid-01
- Preview: https://pagesugar.com/preview/pricing-grid-01

## Variants

| Variant | Label | Default | Artifact digest |
| --- | --- | --- | --- |
| `neutral` | Neutral | yes | `sha256-7e41bda56205cd6856dc7c9f75e6a0558e35caddd725e84c321307c88188dfe3` |
| `blue` | Blue accent | no | `sha256-ecfc5672fef1b6b01e377bd5369b44ceb83b58253134f1ac187f117f28130fc8` |

## Runtime and compatibility

- Runtime: svelte
- Svelte: 5
- SvelteKit required: no (portable Svelte component)
- Tailwind CSS: 4
- SSR: supported
- Requires client-side JavaScript: no
- Integration level: presentational
- Appearance modes: light
- Suggested directory: `src/lib/components/pricing-grid-01`

## Dependencies

No third-party runtime packages.

## Services

No external services required.

## Usage

Presentational only: every label, price and feature is displayed exactly as supplied by your data, and each plan button is an ordinary link. No additional runtime packages beyond Svelte and Tailwind CSS and no backend. Point each link at your own checkout, signup or contact flow.

Required props: `plans`, `title`

```svelte
<!-- Illustrative content: replace example claims, prices and links before publishing. -->
<script lang="ts">
	import PricingGrid, { type PricingPlan } from '$lib/components/pricing-grid-01/PricingGrid.svelte';

	const plans: PricingPlan[] = [
		{
			label: 'Starter',
			price: '$9',
			period: 'per month',
			features: ['One project', 'Email support'],
			cta: { label: 'Choose Starter', href: '/signup?plan=starter' }
		},
		{
			label: 'Team',
			price: '$29',
			period: 'per month',
			features: ['Unlimited projects', 'Shared workspaces'],
			cta: { label: 'Choose Team', href: '/signup?plan=team' },
			recommended: true
		}
	];
</script>

<PricingGrid title="Plans and pricing" {plans} />
```

Limitations:

- Does not create subscriptions, calculate totals, apply tax or switch currencies; prices are display strings.
- No billing-period toggle; render a second grid or edit the source if you need one.
- Light appearance only.

## Usage guide

### Connecting the plan links

Copy `PricingGrid.svelte` into `src/lib/components/pricing-grid-01/`. Replace the example plans, prices, features and destinations with your real offer. Each `cta.href` is an ordinary link; the grid does not create a subscription or process a payment.

`PricingPlan` is exported from the component’s module script. Its shape is `{ label, price, period?, description?, features, cta: { label, href }, recommended? }`.

#### Adjusting the accent

Set both public variables on an ancestor so the accent and its text colour stay together:

```svelte
<div style="--pricing-grid-accent: #1d4ed8; --pricing-grid-on-accent: #ffffff;">
	<PricingGrid title="Plans and pricing" {plans} />
</div>
```

White on-accent text measures about 17.7:1 on the neutral accent (`#18181b`) and 6.7:1 on the blue accent (`#1d4ed8`), using the WCAG relative-luminance formula. These figures describe those pairs only. Re-check contrast after either colour changes.

## Props

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `plans` | `PricingPlan[]` | yes |  | Plans in display order. Each has label, price (display string), optional period and description, features (string\[\]), cta { label, href } and an optional recommended flag. |
| `title` | `string` | yes |  | Section heading text. |
| `description` | `string` | no |  | Optional introductory paragraph under the heading. |
| `headingLevel` | 2 \| 3 \| 4 \| 5 | no | `2` | Level of the section heading; plan names use the next level down. |
| `recommendedLabel` | `string` | no | `'Recommended'` | Badge text shown on plans with recommended: true. |

## Customization

Change content through the plans prop, change the accent colour through two CSS variables, and edit Tailwind classes in the source for spacing, radius or layout.

- Colours: set --pricing-grid-accent and --pricing-grid-on-accent on any ancestor; keep the pair at 4.5:1 contrast or better because the on-accent colour is used for button and badge text.
- Links: replace each cta.href with your real checkout, signup or contact route and make cta.label specific (e.g. "Choose Team").
- Headings: set headingLevel so the section heading fits the page outline; plan names automatically use the next level.
- Layout: cards wrap using basis-64 and max-w-sm on each list item; change those classes to alter card width or column count.
- Recommended plan: mark at most one plan recommended so the emphasis stays meaningful.
- Surface: the section has no background of its own; place it on a white or light neutral page, or add a bg-\* class to the root section.

| Token | Public CSS variable |
| --- | --- |
| `accent` | `--pricing-grid-accent` |
| `onAccent` | `--pricing-grid-on-accent` |

## Accessibility

- Plans are a semantic list; each plan name is a heading one level below the section heading, which is set with headingLevel.
- Each plan link is described by its plan heading via aria-describedby, so repeated labels such as "Get started" remain distinguishable.
- The recommended plan is identified by visible badge text, not colour alone.
- White (#ffffff) on-accent text measures about 17.7:1 against the neutral accent (#18181b) and about 6.7:1 against the blue accent (#1d4ed8), computed with the WCAG relative-luminance formula; links show a visible focus outline in the accent colour.
- Checkmark icons are decorative and hidden from assistive technology.
- Element IDs come from $props.id(), so multiple grids on one page stay unique and hydrate deterministically.

Known limitations:

- Contrast ratios are computed for the two shipped palettes only; any changed accent or on-accent colour must be re-checked for at least 4.5:1.

## License

- Declared source: MIT
- Default license approval is pending. See https://pagesugar.com/docs/license.

## Artifacts

### Neutral (`neutral`) (default)

- Artifact digest: `sha256-7e41bda56205cd6856dc7c9f75e6a0558e35caddd725e84c321307c88188dfe3`
- Entry: `PricingGrid.svelte`
- Receipt: https://pagesugar.com/artifacts/cmp_pricing_grid_001/1.0.0/neutral/sha256-7e41bda56205cd6856dc7c9f75e6a0558e35caddd725e84c321307c88188dfe3/manifest.json
- Bundle: https://pagesugar.com/artifacts/cmp_pricing_grid_001/1.0.0/neutral/sha256-7e41bda56205cd6856dc7c9f75e6a0558e35caddd725e84c321307c88188dfe3/bundle.zip (3812 bytes, sha256 `53ae511a644b065343e36c6bd52608e70351b7e353a069ba8895ca21ea35042e`)

Files:

- `PricingGrid.svelte` (entry, 3864 bytes): https://pagesugar.com/artifacts/cmp_pricing_grid_001/1.0.0/neutral/sha256-7e41bda56205cd6856dc7c9f75e6a0558e35caddd725e84c321307c88188dfe3/source/PricingGrid.svelte

### Blue accent (`blue`)

- Artifact digest: `sha256-ecfc5672fef1b6b01e377bd5369b44ceb83b58253134f1ac187f117f28130fc8`
- Entry: `PricingGrid.svelte`
- Receipt: https://pagesugar.com/artifacts/cmp_pricing_grid_001/1.0.0/blue/sha256-ecfc5672fef1b6b01e377bd5369b44ceb83b58253134f1ac187f117f28130fc8/manifest.json
- Bundle: https://pagesugar.com/artifacts/cmp_pricing_grid_001/1.0.0/blue/sha256-ecfc5672fef1b6b01e377bd5369b44ceb83b58253134f1ac187f117f28130fc8/bundle.zip (3816 bytes, sha256 `e552261ad9feb5aa234e7649e7d02bf8801c6b8ee91b6e1d881c73074563c46a`)

Files:

- `PricingGrid.svelte` (entry, 3864 bytes): https://pagesugar.com/artifacts/cmp_pricing_grid_001/1.0.0/blue/sha256-ecfc5672fef1b6b01e377bd5369b44ceb83b58253134f1ac187f117f28130fc8/source/PricingGrid.svelte
