Components
A morphing side-by-side comparison component with expandable panels, SVG score rings, tug-of-war attribute bars, and an animated verdict summary. Click either panel to expand it while the other recedes. Built with Lora + Figtree. Fully responsive, dark mode compatible, and content-agnostic — compare frameworks, tools, approaches, or anything else.
Loading preview...
import { Component as ComparisonBlock } from "@/components/ui/comparison-block";
const sideA = {
name: "Traditional Stack",
description: "The battle-tested approach with years of community support.",
badge: "Legacy",
image: "https://images.unsplash.com/photo-1555066931-4365d14bab8c?q=80&w=1280&auto=format&fit=crop",
highlights: ["Mature ecosystem", "Large talent pool", "Proven patterns"],
};
const sideB = {
name: "Modern Stack",
description: "Built for the edge. Type-safe by default. Zero compromise.",
badge: "Recommended",
image: "https://images.unsplash.com/photo-1618477388954-7852f32655ec?q=80&w=1280&auto=format&fit=crop",
highlights: [
"Type-safe by default",
"Edge-first architecture",
"Built-in optimizations",
"Zero-config tooling",
],
};
const attributes = [
{ label: "Performance", sideA: { value: "Good", score: 60 }, sideB: { value: "Exceptional", score: 95 } },
{ label: "DX", sideA: { value: "Familiar", score: 70 }, sideB: { value: "Streamlined", score: 92 } },
{ label: "Bundle Size", sideA: { value: "245 KB", score: 45 }, sideB: { value: "18 KB", score: 96 } },
{ label: "Learning Curve", sideA: { value: "Low", score: 90 }, sideB: { value: "Medium", score: 65 } },
{ label: "Type Safety", sideA: { value: "Optional", score: 40 }, sideB: { value: "Built-in", score: 95 } },
{ label: "Scalability", sideA: { value: "Adequate", score: 55 }, sideB: { value: "Excellent", score: 90 } },
{ label: "Ecosystem", sideA: { value: "Massive", score: 95 }, sideB: { value: "Growing", score: 60 } },
{ label: "Future-proof", sideA: { value: "Uncertain", score: 35 }, sideB: { value: "Strong", score: 88 } },
];
export default function Demo() {
return (
<div className="flex min-h-screen items-center justify-center bg-background">
<ComparisonBlock sideA={sideA} sideB={sideB} attributes={attributes} />
</div>
);
}