Getting Started
Templates
Blocks
Components
For solo developers, indie hackers, and freelancers shipping their own products. Pay once, keep everything forever.
Instant download · No subscription · Lifetime access
For small teams, agencies, and freelancers shipping multiple client products. Lifetime access for everyone on your team.
Instant CLI token for 5 seats · Onboarding included · Invoice on request
pnpm dlx shadcn@latest add @ruixenui-pro/pricing-feature-comparisonThe matrix is built on a single 4-column grid that splits into two halves:
col-span-2 md:col-span-1) — the feature column. Each category has a header (title + description) and a list of feature rows. Every feature row pairs the feature name with a tooltip trigger that exposes the longer description on hover or focus.md:col-span-3 md:grid-cols-3) — three plan columns. Each plan has a sticky header card (name, price, CTA) and a stack of value cells aligned to the features on the left.On mobile, the right half collapses to a single column and plan blocks stack vertically; on desktop, all three plans sit side-by-side and the headers stick to the viewport top as you scroll.
The aria-hidden spacers (h-14 md:h-28) at the top of each plan column are what keep value rows aligned with their corresponding feature rows after a category header — they account for the category title block on the left.
Four plans are declared in the PLANS array, each with a priceMonthly and priceAnnual. The popular flag controls the small "Popular" badge next to the plan name and switches the CTA to the primary (filled) variant. Enterprise uses "custom" for both prices, which renders the "Get a custom quote" copy.
const PLANS = [
{ id: "free", name: "Free", priceMonthly: 0, priceAnnual: 0, cta: "Start for free", href: "#" },
{ id: "plus", name: "Plus", priceMonthly: 36, priceAnnual: 29, cta: "Continue with Plus", href: "#" },
{
id: "pro",
name: "Pro",
priceMonthly: 86,
priceAnnual: 69,
cta: "Continue with Pro",
href: "#",
popular: true,
},
{ id: "enterprise", name: "Enterprise", priceMonthly: "custom", priceAnnual: "custom", cta: "Talk to sales", href: "#" },
]The Monthly/Annual toggle in the features column header is a controlled segmented control with a sliding thumb (translate-x between the two button positions, 500ms ease). Toggling updates a billing state, and every plan header reads billing === "monthly" ? plan.priceMonthly : plan.priceAnnual to render the right number and label.
Five categories ship by default: Platform, Infrastructure, Support, Analytics, and Security. Each feature carries values keyed by plan id.
const CATEGORIES = [
{
title: "Platform",
description: "Core features that enable seamless operations of your SaaS",
features: [
{
name: "Unlimited Storage",
description: "Cloud storage for your team's assets and uploads.",
values: { free: "2 GB", plus: "25 GB", pro: "100 GB", enterprise: "Unlimited" },
},
// ...
],
},
// ...
]A value can be:
true — renders as a green check chip.false — renders as a muted dash chip."2 GB", "Unlimited", "30 days").lucide-react — for the check and dash icons.button and tooltip primitives.