Skip to content

Blue accent palette · 3.7 KB ZIP File receipt View code

Preview

Fit to the available width. Previews taller than the maximum auto-height scroll inside the frame.

Use this component with your coding agent

Using the PageSugar MCP server, fetch component cmp_pricing_grid_001 version 1.0.0 with variant "blue", first inspect its requirements and license status and confirm this project uses Svelte 5 and Tailwind CSS 4. Retrieve every manifest file, including binary assets and any manifest-only response files, preserving relative paths. Then integrate the source and follow its usage notes. Run project checks, review the browser result and report anything unverified. Do not substitute another version or invent missing files.

Code

Blue accent palette, version 1.0.0. Artifact sha256-ecfc5672fef1b6b01e377bd5369b44ceb83b58253134f1ac187f117f28130fc8

PricingGrid.svelte · Svelte component · 3.8 KB

<script module lang="ts">
	export interface PricingPlan {
		/** Plan name shown as the card heading. */
		label: string;
		/** Display-only price string, e.g. "$12". Never parsed or charged. */
		price: string;
		/** Billing period shown after the price, e.g. "per month". */
		period?: string;
		description?: string;
		features: string[];
		cta: { label: string; href: string };
		recommended?: boolean;
	}
</script>

<script lang="ts">
	interface Props {
		plans: PricingPlan[];
		title: string;
		description?: string;
		headingLevel?: 2 | 3 | 4 | 5;
		recommendedLabel?: string;
	}

	let {
		plans,
		title,
		description,
		headingLevel = 2,
		recommendedLabel = 'Recommended'
	}: Props = $props();

	const uid = $props.id();
	const sectionHeading = $derived(`h${headingLevel}`);
	const planHeading = $derived(`h${headingLevel + 1}`);
</script>

<section class="pricing-grid px-4 py-16 sm:px-6 lg:px-8" aria-labelledby="{uid}-title">
	<div class="mx-auto max-w-6xl">
		<div class="mx-auto max-w-2xl text-center">
			<svelte:element
				this={sectionHeading}
				id="{uid}-title"
				class="text-3xl font-semibold tracking-tight text-balance text-zinc-900 sm:text-4xl"
			>
				{title}
			</svelte:element>
			{#if description}
				<p class="mt-4 text-base text-pretty text-zinc-600 sm:text-lg">{description}</p>
			{/if}
		</div>

		<ul class="mt-12 flex flex-wrap justify-center gap-6" role="list">
			{#each plans as plan, index (index)}
				<li
					class={[
						'flex max-w-sm min-w-0 grow basis-64 flex-col rounded-2xl bg-white p-6 sm:p-8',
						plan.recommended ? 'shadow-sm ring-2 ring-[var(--_accent)]' : 'ring-1 ring-zinc-200'
					]}
				>
					<div class="flex flex-wrap items-start justify-between gap-x-4 gap-y-2">
						<svelte:element
							this={planHeading}
							id="{uid}-plan-{index}"
							class="text-lg font-semibold break-words text-zinc-900"
						>
							{plan.label}
						</svelte:element>
						{#if plan.recommended}
							<p
								class="rounded-full bg-[var(--_accent)] px-2.5 py-1 text-xs font-medium text-[var(--_on-accent)]"
							>
								{recommendedLabel}
							</p>
						{/if}
					</div>

					{#if plan.description}
						<p class="mt-3 text-sm text-pretty text-zinc-600">{plan.description}</p>
					{/if}

					<p class="mt-6 flex flex-wrap items-baseline gap-x-2">
						<span class="text-4xl font-semibold tracking-tight break-all text-zinc-900"
							>{plan.price}</span
						>
						{#if plan.period}
							<span class="text-sm text-zinc-600">{plan.period}</span>
						{/if}
					</p>

					<ul class="mt-6 flex-1 space-y-3 text-sm text-zinc-700" role="list">
						{#each plan.features as feature, featureIndex (featureIndex)}
							<li class="flex gap-3">
								<svg
									class="mt-0.5 size-4 shrink-0 text-zinc-900"
									viewBox="0 0 16 16"
									fill="none"
									aria-hidden="true"
								>
									<path
										d="M3.5 8.5l3 3 6-7"
										stroke="currentColor"
										stroke-width="1.75"
										stroke-linecap="round"
										stroke-linejoin="round"
									/>
								</svg>
								<span class="min-w-0 break-words">{feature}</span>
							</li>
						{/each}
					</ul>

					<a
						href={plan.cta.href}
						aria-describedby="{uid}-plan-{index}"
						class={[
							'mt-8 block rounded-lg px-4 py-2.5 text-center text-sm font-semibold focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--_accent)]',
							plan.recommended
								? 'bg-[var(--_accent)] text-[var(--_on-accent)] hover:opacity-90'
								: 'text-zinc-900 ring-1 ring-zinc-300 ring-inset hover:bg-zinc-50'
						]}
					>
						{plan.cta.label}
					</a>
				</li>
			{/each}
		</ul>
	</div>
</section>

<style>
	.pricing-grid {
		--_accent: var(--pricing-grid-accent, #1d4ed8);
		--_on-accent: var(--pricing-grid-on-accent, #ffffff);
	}
</style>

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.

Suggested location: src/lib/components/pricing-grid-01

Required props: plans, title

Example

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.

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.

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.

Public CSS variables

VariableToken
--pricing-grid-accentaccent
--pricing-grid-on-accentonAccent

Props and content inputs

NameTypeRequiredDefaultDescription
plansPricingPlan[]YesNonePlans in display order. Each has label, price (display string), optional period and description, features (string[]), cta { label, href } and an optional recommended flag.
titlestringYesNoneSection heading text.
descriptionstringNoNoneOptional introductory paragraph under the heading.
headingLevel2 | 3 | 4 | 5No2Level of the section heading; plan names use the next level down.
recommendedLabelstringNo'Recommended'Badge text shown on plans with recommended: true.

Dependencies and services

No additional runtime packages beyond Svelte and Tailwind CSS.

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 license: MIT.

Default license approval is pending. See the license status before adopting the source.

Version history

Only the current release is available. Keep downloaded source and its receipt if you need to use it again later.

  • 1.0.0 Published current · selected · 16 September 2026

Search components

Describe a section or control, such as “FAQ accordion” or “newsletter signup”.