UI Library
Single pricing card
One plan, one price, a checklist of what it includes, and a single call to action. The honest shape for a product that has not split into tiers yet.
Pricingsingle-tierchecklistcard
Preview
Current plan
Free
— for every user, every workspace.
- Unlimited projects, tasks and notes.
- Unlimited workspaces and members.
- Two-way sync with the editor extensions.
- Optional repository sync.
- EU hosting, opt-out analytics, no cross-site tracking.
apps/site/blocks/components/pricing-single-card.tsx
import { Check } from 'lucide-react';
const DEFAULT_FEATURES = [
'Unlimited projects, tasks and notes.',
'Unlimited workspaces and members.',
'Two-way sync with the editor extensions.',
'Optional repository sync.',
'EU hosting, opt-out analytics, no cross-site tracking.',
];
export function PricingSingleCard({
eyebrow = 'Current plan',
price = 'Free',
note = '— for every user, every workspace.',
features = DEFAULT_FEATURES,
cta = { label: 'Sign in', href: '#' },
}: {
eyebrow?: string;
price?: string;
note?: string;
features?: string[];
cta?: { label: string; href: string };
}) {
return (
<div className="mx-auto max-w-2xl px-4 py-16 sm:px-6">
<div className="rounded-xl border border-border bg-card p-8">
<div className="text-xs font-medium uppercase tracking-widest text-primary">{eyebrow}</div>
{/* items-baseline so the note sits on the price's baseline rather than
centring against a 4xl line box. */}
<div className="mt-2 flex items-baseline gap-2">
<div className="text-4xl font-semibold tracking-tight">{price}</div>
<div className="text-sm text-muted-foreground">{note}</div>
</div>
<ul className="mt-6 space-y-2 text-sm">
{features.map((line) => (
<li key={line} className="flex items-start gap-2">
<Check className="mt-0.5 h-4 w-4 shrink-0 text-primary" />
<span>{line}</span>
</li>
))}
</ul>
<div className="mt-8">
<a
href={cta.href}
className="inline-flex h-10 items-center rounded-md bg-primary px-5 text-sm font-medium text-primary-foreground shadow-sm transition-colors hover:bg-primary/90"
>
{cta.label}
</a>
</div>
</div>
</div>
);
}
Dependencies
lucide-react— npm package
Colours come from CSS variables (--background, --primary, --border) using the shadcn/ui token names, so the block adopts your palette rather than importing ours.