Blox/
Feature Comparison
A comprehensive feature comparison table for comparing plans, products, or services. Perfect for pricing pages, product comparisons, and SaaS landing pages.
Comparison GridFeature CategoriesHighlight PopularCTA Buttons
Installation
Terminal
TSXReactTailwind
npx @uiblox/cli add feature-comparisonPreview
Layout:
Compare
Starter
$9/mo
Popular
Pro
$29/mo
Enterprise
$99/mo
Projects
5
Unlimited
Unlimited
Storage
10GB
100GB
Unlimited
API Access
Priority support
Use Cases
SaaS Pricing Pages
Help customers choose the right plan by comparing features across tiers.
Product Comparisons
Compare different products, versions, or editions side by side.
Service Packages
Display different service levels and what's included in each.
Tool Comparisons
Compare your product against competitors with feature matrices.
Source Code
feature-comparison.tsx
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113"use client"; import { useState } from "react"; import { cn } from "@/lib/utils"; interface Plan { name: string; price: string; description: string; popular?: boolean; } interface Feature { name: string; category: string; plans: { [key: string]: boolean | string }; } const plans: Plan[] = [ { name: "Starter", price: "$9", description: "For individuals" }, { name: "Pro", price: "$29", description: "For teams", popular: true }, { name: "Enterprise", price: "$99", description: "For organizations" }, ]; const features: Feature[] = [ { name: "Projects", category: "Core Features", plans: { Starter: "5", Pro: "Unlimited", Enterprise: "Unlimited" } }, { name: "Storage", category: "Core Features", plans: { Starter: "10GB", Pro: "100GB", Enterprise: "Unlimited" } }, { name: "Team members", category: "Core Features", plans: { Starter: "1", Pro: "10", Enterprise: "Unlimited" } }, { name: "API Access", category: "Developer", plans: { Starter: false, Pro: true, Enterprise: true } }, { name: "Webhooks", category: "Developer", plans: { Starter: false, Pro: true, Enterprise: true } }, { name: "Custom integrations", category: "Developer", plans: { Starter: false, Pro: false, Enterprise: true } }, { name: "Basic analytics", category: "Analytics", plans: { Starter: true, Pro: true, Enterprise: true } }, { name: "Advanced reports", category: "Analytics", plans: { Starter: false, Pro: true, Enterprise: true } }, { name: "Custom dashboards", category: "Analytics", plans: { Starter: false, Pro: false, Enterprise: true } }, { name: "Email support", category: "Support", plans: { Starter: true, Pro: true, Enterprise: true } }, { name: "Priority support", category: "Support", plans: { Starter: false, Pro: true, Enterprise: true } }, { name: "Dedicated manager", category: "Support", plans: { Starter: false, Pro: false, Enterprise: true } }, ]; export function FeatureComparison() { const categories = [...new Set(features.map(f => f.category))]; return ( <div className="bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-slate-800 overflow-hidden"> {/* Header */} <div className="grid grid-cols-4 border-b border-slate-200 dark:border-slate-800"> <div className="p-6 bg-slate-50 dark:bg-slate-800/50"> <h2 className="text-lg font-semibold text-slate-900 dark:text-white">Compare Plans</h2> <p className="text-sm text-slate-500 mt-1">Find the perfect plan for your needs</p> </div> {plans.map((plan) => ( <div key={plan.name} className={cn("p-6 text-center", plan.popular && "bg-purple-50 dark:bg-purple-900/10")}> {plan.popular && ( <span className="inline-block px-2 py-0.5 bg-purple-600 text-white text-xs font-medium rounded-full mb-2">Popular</span> )} <h3 className="text-lg font-bold text-slate-900 dark:text-white">{plan.name}</h3> <p className="text-2xl font-bold text-slate-900 dark:text-white mt-1">{plan.price}<span className="text-sm font-normal text-slate-500">/mo</span></p> <p className="text-sm text-slate-500 mt-1">{plan.description}</p> </div> ))} </div> {/* Features */} {categories.map((category) => ( <div key={category}> <div className="px-6 py-3 bg-slate-50 dark:bg-slate-800/50 border-b border-slate-200 dark:border-slate-800"> <h4 className="text-sm font-semibold text-slate-700 dark:text-slate-300">{category}</h4> </div> {features.filter(f => f.category === category).map((feature) => ( <div key={feature.name} className="grid grid-cols-4 border-b border-slate-100 dark:border-slate-800 hover:bg-slate-50 dark:hover:bg-slate-800/30"> <div className="p-4 text-sm text-slate-600 dark:text-slate-400">{feature.name}</div> {plans.map((plan) => { const value = feature.plans[plan.name]; return ( <div key={plan.name} className={cn("p-4 text-center", plan.popular && "bg-purple-50/50 dark:bg-purple-900/5")}> {typeof value === "boolean" ? ( value ? <CheckIcon className="mx-auto text-emerald-500" /> : <XIcon className="mx-auto text-slate-300 dark:text-slate-600" /> ) : ( <span className="text-sm font-medium text-slate-900 dark:text-white">{value}</span> )} </div> ); })} </div> ))} </div> ))} {/* CTA */} <div className="grid grid-cols-4 border-t border-slate-200 dark:border-slate-800"> <div className="p-6"></div> {plans.map((plan) => ( <div key={plan.name} className={cn("p-6 text-center", plan.popular && "bg-purple-50 dark:bg-purple-900/10")}> <button className={cn( "w-full py-2.5 rounded-xl font-semibold transition-colors", plan.popular ? "bg-purple-600 hover:bg-purple-700 text-white" : "bg-slate-100 dark:bg-slate-800 hover:bg-slate-200 dark:hover:bg-slate-700 text-slate-900 dark:text-white" )}> Get Started </button> </div> ))} </div> </div> ); } function CheckIcon({ className }: { className?: string }) { return <svg className={cn("w-5 h-5", className)} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" /></svg>; } function XIcon({ className }: { className?: string }) { return <svg className={cn("w-5 h-5", className)} fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /></svg>; }