Getting Started
Templates
Blocks
Components
A long-form pricing comparison table where features are grouped into named sections (Content, AI features, Admin & security, etc.). Sticky four-plan header with prices and CTAs; left-column section labels and feature rows below. Designed for product surfaces with many features and clear category boundaries.
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-sectioned-gridA single 5-column grid template — 200px for section labels + feature names, then 1fr for each of the four plans. The template is shared across the sticky header and every feature row so columns line up perfectly.
top-[var(--header-height,0px)] so it docks under your site header on the actual page. The variable falls through to 0px when the component is rendered in isolation (e.g. inside a docs preview iframe).border-t, so the table reads as a continuous list of rows broken up by section labels.min-w-[860px] on the grid). On phones, the table scrolls horizontally rather than collapsing into something illegible.Plans are 4 fixed entries — Free / Plus / Business / Enterprise. The Enterprise plan uses price: null to render a "Contact us" link with an arrow instead of a price + button.
const PLANS = [
{ id: "free", name: "Free", price: 0, priceSuffix: "per seat/month", cta: "Sign up", href: "#" },
{ id: "plus", name: "Plus", price: 12, priceSuffix: "per seat/month", cta: "Get started", href: "#" },
{ id: "business", name: "Business", price: 24, priceSuffix: "per seat/month", cta: "Get started", href: "#" },
{ id: "enterprise", name: "Enterprise", price: null, cta: "Contact us", href: "#" },
]Sections are a flat array; each carries a label and a list of features. Each feature has a name, optional tooltip, optional beta flag, and a values object keyed by plan id.
const SECTIONS = [
{
label: "Content",
features: [
{
name: "Page history",
tooltip: "How far back you can restore a page to a previous version.",
values: { free: "7 days", plus: "30 days", business: "90 days", enterprise: "Unlimited" },
},
// ...
],
},
// ...
]Value cells render three ways:
true → green check iconfalse → empty cell (with an sr-only "Not included" for screen readers)"Unlimited", "30 days", "Limited Trial", "Pay per domain", etc.)Features with a tooltip get a hover-tooltip on the feature name (wrapped in a <button> so it's keyboard-focusable). Features with beta: true get a small "Beta" pill rendered next to the name.
SECTIONS array. The component renders sections in order.PlanId union, add an entry to PLANS, then make sure every feature's values object includes the new key.CellValue union (e.g. add "icon" for integration icons, or a structured object for icons + caption).lucide-react — Check and ArrowRight iconsbutton and tooltip primitives