Pricing Comparison Matrix
A free grouped pricing section for comparing plans in detail, with sticky labels and a focused differences-only view.
Plans
Compare every detail
Start small, then move up when your team needs deeper controls.
| Features | LaunchFor solo builders shipping their first product.$12/monthChoose Launch | Recommended ScaleFor growing teams that need controlled workflows.$29/monthChoose Scale | StudioFor organisations managing complex delivery.$79/monthChoose Studio |
|---|---|---|---|
Workspace | |||
Projects | 3 | Unlimited | Unlimited |
Members | 2 | 10 | Unlimited |
Guest access | Not included | Included | Included |
Workflow | |||
Automations | 100 / month | 5,000 / month | Unlimited |
Version history | 7 days | 90 days | Unlimited |
Approval flows | Not included | Included | Included |
Support and security | |||
Email support | Included | Included | Included |
Priority support | Not included | Included | Included |
SSO | Not included | Not included | Included |
Customise
Code
<PricingComparisonMatrix
eyebrow="Plans"
title="Compare every detail"
description="Start small, then move up when your team needs deeper controls."
plans={[
{
id: "launch",
name: "Launch",
description: "For solo builders shipping their first product.",
price: 12,
period: "/month",
cta: { label: "Choose Launch", href: "/signup/launch" },
},
{
id: "scale",
name: "Scale",
description: "For growing teams that need controlled workflows.",
price: 29,
period: "/month",
cta: { label: "Choose Scale", href: "/signup/scale" },
recommended: true,
},
{
id: "studio",
name: "Studio",
description: "For organisations managing complex delivery.",
price: 79,
period: "/month",
cta: { label: "Choose Studio", href: "/signup/studio" },
},
]}
groups={[
{
id: "workspace",
heading: "Workspace",
features: [
{
id: "projects",
label: "Projects",
values: { launch: "3", scale: "Unlimited", studio: "Unlimited" },
},
{
id: "members",
label: "Members",
values: { launch: "2", scale: "10", studio: "Unlimited" },
},
{
id: "guest-access",
label: "Guest access",
values: { launch: false, scale: true, studio: true },
},
],
},
{
id: "workflow",
heading: "Workflow",
features: [
{
id: "automations",
label: "Automations",
values: {
launch: "100 / month",
scale: "5,000 / month",
studio: "Unlimited",
},
},
{
id: "version-history",
label: "Version history",
values: {
launch: "7 days",
scale: "90 days",
studio: "Unlimited",
},
},
{
id: "approval-flows",
label: "Approval flows",
values: { launch: false, scale: true, studio: true },
},
],
},
{
id: "support-security",
heading: "Support and security",
features: [
{
id: "email-support",
label: "Email support",
values: { launch: true, scale: true, studio: true },
},
{
id: "priority-support",
label: "Priority support",
values: { launch: false, scale: true, studio: true },
},
{
id: "sso",
label: "SSO",
values: { launch: false, scale: false, studio: true },
},
],
},
]}
/>Pricing Comparison Matrix is a free pricing section for Next.js and React, built with Motion and Tailwind to present plan prices, calls to action and grouped product features in one native table.
Its differences-only view removes identical rows while the remaining groups settle into place, making it a denser decision tool than pricing-highlight-sweep and its pointer-following column emphasis.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/pricing-comparison-matrixUsage
import {
PricingComparisonMatrix,
type PricingComparisonGroup,
type PricingComparisonPlan,
} from "@/components/pricing-comparison-matrix";
const plans: PricingComparisonPlan[] = [
{
id: "launch",
name: "Launch",
description: "For solo builders shipping their first product.",
price: 12,
period: "/month",
cta: { label: "Choose Launch", href: "/signup/launch" },
},
{
id: "scale",
name: "Scale",
description: "For growing teams that need controlled workflows.",
price: 29,
period: "/month",
cta: { label: "Choose Scale", href: "/signup/scale" },
recommended: true,
},
{
id: "studio",
name: "Studio",
description: "For organisations managing complex delivery.",
price: 79,
period: "/month",
cta: { label: "Choose Studio", href: "/signup/studio" },
},
];
const groups: PricingComparisonGroup[] = [
{
id: "workspace",
heading: "Workspace",
features: [
{
id: "projects",
label: "Projects",
values: { launch: "3", scale: "Unlimited", studio: "Unlimited" },
},
{
id: "members",
label: "Members",
values: { launch: "2", scale: "10", studio: "Unlimited" },
},
{
id: "guest-access",
label: "Guest access",
values: { launch: false, scale: true, studio: true },
},
],
},
{
id: "workflow",
heading: "Workflow",
features: [
{
id: "automations",
label: "Automations",
values: {
launch: "100 / month",
scale: "5,000 / month",
studio: "Unlimited",
},
},
{
id: "version-history",
label: "Version history",
values: {
launch: "7 days",
scale: "90 days",
studio: "Unlimited",
},
},
{
id: "approval-flows",
label: "Approval flows",
values: { launch: false, scale: true, studio: true },
},
],
},
{
id: "support-security",
heading: "Support and security",
features: [
{
id: "email-support",
label: "Email support",
values: { launch: true, scale: true, studio: true },
},
{
id: "priority-support",
label: "Priority support",
values: { launch: false, scale: true, studio: true },
},
{
id: "sso",
label: "SSO",
values: { launch: false, scale: false, studio: true },
},
],
},
];
export default function Page() {
return (
<PricingComparisonMatrix
eyebrow="Plans"
title="Compare every detail"
description="Start small, then move up when your team needs deeper controls."
plans={plans}
groups={groups}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow | string | undefined | Optional small label rendered above the section heading. |
| title | string | required | Section heading rendered as an h2. |
| description | string | undefined | Optional supporting paragraph beneath the heading. |
| plans | PricingComparisonPlan[] | required | Two to four plan columns in display order. Each plan has a stable ID, name, numeric price, call to action, optional description and period, and an optional recommended state. |
| groups | PricingComparisonGroup[] | required | Two or more labelled feature groups. Feature values are keyed by plan ID; true means included, false means not included, null or a missing key means not available, and strings render verbatim. |
| currency | string | "$" | Prefix rendered before every numeric plan price. |
| differencesLabel | string | "Show differences only" | Visible and accessible label for the differences view switch. |
| defaultView | "all" | "differences" | "all" | Deterministic initial view rendered by server and client. Differences filters rows whose normalised values are identical across every rendered plan. |
| density | "comfortable" | "compact" | "comfortable" | Changes cell spacing and type scale without changing motion timing. |
| stickyHeader | boolean | true | Keeps plan headings at the block start while the matrix passes. Feature labels remain sticky horizontally at either value. |
| className | string | undefined | Additional classes merged onto the root section. |
Customisation
Choose comfortable or compact density for the table geometry, then retheme the small active accents, opaque sticky cells and row rules with the --pricing-matrix-active, --pricing-matrix-sticky and --pricing-matrix-rule component tokens. Text and calls to action continue to use the global semantic tokens.
<PricingComparisonMatrix
className="pricing-comparison"
density="compact"
title="Compare every detail"
plans={plans}
groups={groups}
/>
.pricing-comparison {
--pricing-matrix-active: var(--primary);
--pricing-matrix-sticky: var(--background);
--pricing-matrix-rule: var(--border);
}Frequently asked questions
- Is Pricing Comparison Matrix free for commercial use?
- Yes. Pricing Comparison Matrix is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Is the comparison table accessible with reduced motion enabled?
- Yes. It uses one native table with a caption and correctly scoped column, row-group and row headers. Boolean marks have hidden Included or Not included text, unavailable values are announced, the scroll region and switch are keyboard focusable, and every call to action is a real anchor. With reduced motion enabled, all visible content appears immediately and filtering, layout changes and the switch thumb update without movement.
- How do I customise density and colours?
- Set density to comfortable or compact to change cell padding and type scale. Override --pricing-matrix-active for badges and the switch thumb, --pricing-matrix-sticky for opaque sticky cells, and --pricing-matrix-rule for table borders. The remaining text and call-to-action colours follow your semantic theme tokens.