Comparison table
BlockA feature grid comparing plans or products row by row.
pnpm dlx shadcn@latest add https://caliperui.site/r/comparison-table.jsonWhen to use #
Use it for
- The details matter more than the headline price.
Skip it when
- Fewer than four rows.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/comparison-table.json
Adds its 2 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
example.tsx
import { ComparisonTable } from "@/components/ui/comparison-table" const plans = [ { id: "starter", name: "Starter", description: "For trying things out.", price: { monthly: 0, yearly: 0 }, features: ["40 components", "Community support", "Personal projects"], cta: "Start free" }, { id: "team", name: "Team", description: "For shipping a product.", price: { monthly: 24, yearly: 19 }, features: ["Every component and block", "Private repository access", "Email support", "Unlimited projects"], cta: "Choose Team", highlighted: true, badge: "Most popular" }, { id: "business", name: "Business", description: "For admin controls.", price: { monthly: 48, yearly: 40 }, features: ["Everything in Team", "Priority support", "Seat management", "Custom license terms"], cta: "Choose Business" }, { id: "enterprise", name: "Enterprise", description: "For custom needs.", price: "Talk to us", features: ["Everything in Business", "Security review", "Dedicated contact"], cta: "Contact sales" }, ]; const compare = [ { id: "starter", name: "Starter" }, { id: "team", name: "Team", highlight: true }, { id: "business", name: "Business" }, ]; const groups = [ { title: "Library", rows: [ { label: "Components", values: { starter: "40", team: "200+", business: "200+" } }, { label: "Blocks and screens", hint: "Whole sections you can edit", values: { starter: false, team: true, business: true } }, { label: "Agent interface kit", values: { starter: false, team: true, business: true } }, ] }, { title: "Support", rows: [ { label: "Community", values: { starter: true, team: true, business: true } }, { label: "Email support", values: { starter: false, team: "2 days", business: "1 day" } }, { label: "Seat management", values: { starter: false, team: false, business: true } }, ] }, ]; export function ComparisonTableDemo() { return ( <ComparisonTable plans={compare} groups={groups} /> ); }
API reference #
ComparisonTable
component
PropTypeDefault
plans *readonly ComparisonPlan[]—
groups *readonly ComparisonGroup[]—
captionstring"Compare plans"
classNamestring—
Accessibility #
It exposes region semantics, with aria-label and aria-hidden kept in step with state.
No custom key handling; Tab and the native activation keys do the work.
Motion #
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.