Components
3D deck of frosted-glass cards with immersive interaction. Scroll, drag, or use arrow keys to navigate a curved 3D carousel featuring frosted-glass styling, animated mesh gradients, smooth spring physics, and premium micro-interactions.

"use client";
import CardFan, { type FanCardData } from "@/components/ui/card-fan";
/* ------------------------------------------------------------------ *
* Demo 1 — project portfolio (default accent)
* ------------------------------------------------------------------ */
const PROJECTS: FanCardData[] = [
{
id: "p1", code: "Northwind", kicker: "IN BUILD",
title: "Rebuilding the checkout flow on the new payments core",
value: 42, total: 60, progress: 72,
stats: [
{ label: "Tasks done", value: "42 / 60" },
{ label: "Squad", value: 6 },
{ label: "Blockers", value: 4, alert: true },
],
},
{
id: "p2", code: "Halcyon", kicker: "IN BUILD",
title: "Realtime collaboration layer for the shared workspace",
value: 36, total: 50, progress: 64,
stats: [
{ label: "Tasks done", value: "36 / 50" },
{ label: "Squad", value: 4 },
{ label: "Blockers", value: 7, alert: true },
],
},
{
id: "p3", code: "Meridian", kicker: "DISCOVERY",
title: "Usage-based pricing engine and metering pipeline",
value: 24, total: 80, progress: 41,
stats: [
{ label: "Tasks done", value: "24 / 80" },
{ label: "Squad", value: 8 },
{ label: "Blockers", value: 1, alert: true },
],
},
{
id: "p4", code: "Fathom", kicker: "IN REVIEW",
title: "Search relevance rewrite with vector re-ranking",
value: 26, total: 26, progress: 88,
stats: [
{ label: "Tasks done", value: "26 / 26" },
{ label: "Squad", value: 3 },
{ label: "Blockers", value: 0 },
],
},
{
id: "p5", code: "Lantern", kicker: "SHIPPED",
title: "Onboarding redesign and first-run checklist",
value: 58, total: 58, progress: 100, muted: true,
stats: [
{ label: "Tasks done", value: "58 / 58" },
{ label: "Squad", value: 5 },
{ label: "Blockers", value: 0 },
],
},
{
id: "p6", code: "Kestrel", kicker: "SHIPPED",
title: "Mobile offline sync and conflict resolution",
value: 31, total: 31, progress: 100, muted: true,
stats: [
{ label: "Tasks done", value: "31 / 31" },
{ label: "Squad", value: 4 },
{ label: "Blockers", value: 0 },
],
},
{
id: "p7", code: "Solstice", kicker: "ARCHIVED",
title: "Legacy reporting module, superseded by Meridian",
value: 44, total: 44, progress: 100, muted: true,
stats: [
{ label: "Tasks done", value: "44 / 44" },
{ label: "Squad", value: 2 },
{ label: "Blockers", value: 0 },
],
},
];
/* ------------------------------------------------------------------ *
* Demo 2 — release pipeline, violet accent
* ------------------------------------------------------------------ */
const RELEASES: FanCardData[] = [
{
id: "r1", code: "v4.2.0", kicker: "IN QA",
title: "Multi-region failover and the new query planner",
value: 18, total: 24, progress: 74,
stats: [
{ label: "Tickets", value: "18 / 24" },
{ label: "Owner", value: "Platform" },
{ label: "Blockers", value: 2, alert: true },
],
},
{
id: "r2", code: "v4.1.3", kicker: "STAGING",
title: "Batch export, signed URLs and audit streaming",
value: 31, total: 33, progress: 92,
stats: [
{ label: "Tickets", value: "31 / 33" },
{ label: "Owner", value: "Core" },
{ label: "Blockers", value: 0 },
],
},
{
id: "r3", code: "v4.1.2", kicker: "SHIPPED",
title: "Form builder validation rules and regex guard",
value: 27, total: 27, progress: 100, muted: true,
stats: [
{ label: "Tickets", value: "27 / 27" },
{ label: "Owner", value: "Core" },
{ label: "Blockers", value: 0 },
],
},
{
id: "r4", code: "v4.1.1", kicker: "SHIPPED",
title: "Scheduler atomicity fixes and retry semantics",
value: 12, total: 12, progress: 100, muted: true,
stats: [
{ label: "Tickets", value: "12 / 12" },
{ label: "Owner", value: "Platform" },
{ label: "Blockers", value: 0 },
],
},
{
id: "r5", code: "v4.1.0", kicker: "SHIPPED",
title: "Dark theme, glass surfaces and the new app shell",
value: 46, total: 46, progress: 100, muted: true,
stats: [
{ label: "Tickets", value: "46 / 46" },
{ label: "Owner", value: "Design Eng" },
{ label: "Blockers", value: 0 },
],
},
];
export default function CardFanDemo() {
return (
<div className="flex w-full flex-col gap-10 bg-[#0a0a0b] p-6">
<section>
<div className="mb-4 px-2">
<h3 className="text-[26px] font-normal tracking-[-.8px] text-white">
Project <b className="font-semibold">portfolio</b>
</h3>
<p className="mt-2 text-[11.5px] text-white/45">
Scroll, drag or use ← → to browse. Click the focused card to open it.
</p>
</div>
<CardFan
cards={PROJECTS}
unitLabel="PROJECTS"
actionLabel="Open project"
height={560}
onOpen={(c) => console.log("open", c.code)}
/>
</section>
<section>
<div className="mb-4 px-2">
<h3 className="text-[26px] font-normal tracking-[-.8px] text-white">
Release <b className="font-semibold">pipeline</b>
</h3>
<p className="mt-2 text-[11.5px] text-white/45">
Same component with a violet accent and a different record shape.
</p>
</div>
<CardFan
cards={RELEASES}
unitLabel="RELEASES"
actionLabel="Open release"
defaultIndex={1}
height={560}
accent={{ soft: "#b39bff", deep: "#5b34d6", glow: "150,120,255" }}
onOpen={(c) => console.log("open", c.code)}
/>
</section>
</div>
);
}