- Gallery
- Data Display
- ComparisonTable
PremiumNew
ComparisonTable
Feature comparison grid with check/x marks and category grouping
Data Displaycomparisonpricingfeaturesgrid
Dependencies
shadcn/ui components needed:
npx shadcn@latest add cardnpx shadcn@latest add badgeHow to use this component
Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.
Code
1"use client"23import * as React from "react"4import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"5import { Badge } from "@/components/ui/badge"6import { cn } from "@/lib/utils"78interface ComparisonTableProps {9 className?: string10}1112interface Feature {13 category: string14 name: string15 basic: string | boolean16 pro: string | boolean17 enterprise: string | boolean18}1920const features: Feature[] = [21 { category: "Core Features", name: "Projects", basic: true, pro: true, enterprise: true },22 { category: "Core Features", name: "Team Members", basic: "5", pro: "25", enterprise: "Unlimited" },23 { category: "Core Features", name: "Storage", basic: "10 GB", pro: "100 GB", enterprise: "Unlimited" },24 { category: "Advanced", name: "API Access", basic: false, pro: true, enterprise: true },25 { category: "Advanced", name: "Custom Integrations", basic: false, pro: true, enterprise: true },26 { category: "Advanced", name: "Advanced Analytics", basic: false, pro: true, enterprise: true },27 { category: "Support", name: "Email Support", basic: true, pro: true, enterprise: true },28 { category: "Support", name: "Priority Support", basic: false, pro: true, enterprise: true },29 { category: "Support", name: "Dedicated Manager", basic: false, pro: false, enterprise: true },30]3132const categories = Array.from(new Set(features.map(f => f.category)))3334export function ComparisonTable({ className }: ComparisonTableProps) {35 return (36 <Card className={cn("w-full", className)}>37 <CardHeader>38 <CardTitle>Compare Plans</CardTitle>39 </CardHeader>40 <CardContent>41 <div className="grid grid-cols-4 gap-4">42 <div />43 <div className="text-center">44 <h3 className="font-semibold">Basic</h3>45 <Badge variant="outline" className="mt-2">$9/mo</Badge>46 </div>47 <div className={cn("text-center relative p-4 rounded-lg bg-primary/5 ring-2 ring-primary")}>48 <Badge className="absolute -top-2 left-1/2 -translate-x-1/2 text-xs">Popular</Badge>49 <h3 className="font-semibold mt-2">Pro</h3>50 <Badge variant="outline" className="mt-2 bg-primary text-primary-foreground border-primary">$29/mo</Badge>51 </div>52 <div className="text-center">53 <h3 className="font-semibold">Enterprise</h3>54 <Badge variant="outline" className="mt-2">$99/mo</Badge>55 </div>5657 {categories.map((category) => (58 <React.Fragment key={category}>59 <div className="col-span-4 py-2 mt-2 bg-muted/50 rounded-md px-4">60 <span className="font-semibold text-sm">{category}</span>61 </div>62 {features.filter(f => f.category === category).map((feature) => (63 <React.Fragment key={feature.name}>64 <div className="py-3 px-2 text-sm font-medium">{feature.name}</div>65 <div className="py-3 px-2 text-center">66 {typeof feature.basic === "boolean" ? (67 <span className={cn("text-lg", feature.basic ? "text-emerald-500" : "text-red-500")}>68 {feature.basic ? "✓" : "✗"}69 </span>70 ) : (71 <span className="text-sm text-muted-foreground">{feature.basic}</span>72 )}73 </div>74 <div className="py-3 px-2 text-center">75 {typeof feature.pro === "boolean" ? (76 <span className={cn("text-lg", feature.pro ? "text-emerald-500" : "text-red-500")}>77 {feature.pro ? "✓" : "✗"}78 </span>79 ) : (80 <span className="text-sm font-medium">{feature.pro}</span>81 )}82 </div>83 <div className="py-3 px-2 text-center">84 {typeof feature.enterprise === "boolean" ? (85 <span className={cn("text-lg", feature.enterprise ? "text-emerald-500" : "text-red-500")}>86 {feature.enterprise ? "✓" : "✗"}87 </span>88 ) : (89 <span className="text-sm font-medium">{feature.enterprise}</span>90 )}91 </div>92 </React.Fragment>93 ))}94 </React.Fragment>95 ))}96 </div>97 </CardContent>98 </Card>99 )100}