A backend platform's three parts as a list beside the box. Point at a row and its face opens; leave the list and the box walks it again.
registry/demos/black-box-stack-demo.tsx
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
import { BlackBox, type BlackBoxFace } from "@/components/ui/black-box";
// A backend platform's three parts, as a list that opens the box and a box that walks the list.
const LAYERS: (BlackBoxFace & { stat: string })[] = [
{
id: "functions",
label: "Functions",
detail: "TypeScript or Python, deployed on every push, warm in 38 ms.",
stat: "38 ms cold start",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.6} strokeLinecap="round" strokeLinejoin="round">
<path d="M9 7 4 12l5 5M15 7l5 5-5 5" />
</svg>
),
},
{
id: "queues",
label: "Queues",
detail: "Retries, delays and fan-out without a broker to babysit.",
stat: "1.2M jobs a day",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.6} strokeLinecap="round" strokeLinejoin="round">
<path d="M4 7h16M4 12h11M4 17h6" />
</svg>
),
},
{
id: "postgres",
label: "Postgres",
detail: "A branch of your database for every preview, merged with the code.",
stat: "Branch per preview",
icon: (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.6} strokeLinecap="round" strokeLinejoin="round">
<ellipse cx="12" cy="6" rx="7" ry="2.5" />
<path d="M5 6v6c0 1.4 3.1 2.5 7 2.5s7-1.1 7-2.5V6M5 12v6c0 1.4 3.1 2.5 7 2.5s7-1.1 7-2.5v-6" />
</svg>
),
},
];
export function BlackBoxStackDemo() {
const [value, setValue] = React.useState<string | null>(null);
const [holding, setHolding] = React.useState(false);
const [picked, setPicked] = React.useState(false);
return (
<div className="w-full max-w-4xl @container [--black-box-light:#ff5a1f]">
<div className="grid items-center gap-x-10 gap-y-2 @[40rem]:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]">
<div>
<p className="text-xs font-medium tracking-[0.08em] text-[#e2470f] uppercase dark:text-[#ff7a45]">Lattice platform</p>
<h3 className="mt-3 text-3xl font-semibold tracking-[-0.03em] text-balance text-zinc-950 dark:text-white">
Your whole backend, in one box.
</h3>
<ol
className="mt-7 border-t border-zinc-950/10 dark:border-white/10"
onPointerLeave={() => setHolding(false)}
onFocus={() => setHolding(true)}
onBlur={(event) => {
if (!event.currentTarget.contains(event.relatedTarget as Node)) setHolding(false);
}}
>
{LAYERS.map((layer, i) => {
const on = value === layer.id;
return (
<li key={layer.id} className="border-b border-zinc-950/10 dark:border-white/10">
<button
type="button"
aria-pressed={on}
onPointerEnter={(event) => {
if (event.pointerType !== "mouse") return;
setHolding(true);
setValue(layer.id);
}}
onFocus={() => setValue(layer.id)}
onClick={() => {
setPicked(true);
setValue(layer.id);
}}
className="group relative flex w-full gap-4 py-4 text-left outline-none focus-visible:ring-2 focus-visible:ring-[#ff5a1f] focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-zinc-950"
>
<span
aria-hidden
className={cn(
"absolute top-4 bottom-4 -left-px w-0.5 origin-top rounded-full bg-[#ff5a1f] transition-[opacity,transform] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]",
on ? "scale-y-100 opacity-100" : "scale-y-50 opacity-0",
)}
/>
<span className="pl-4 font-mono text-xs leading-6 text-zinc-400 tabular-nums dark:text-zinc-500">
0{i + 1}
</span>
<span className="min-w-0 flex-1">
<span className="flex items-baseline justify-between gap-3">
<span
className={cn(
"text-[15px] leading-6 font-medium tracking-[-0.01em] transition-colors duration-200",
on ? "text-zinc-950 dark:text-white" : "text-zinc-500 dark:text-zinc-400",
)}
>
{layer.label}
</span>
<span className="shrink-0 font-mono text-[11px] text-zinc-400 tabular-nums dark:text-zinc-500">
{layer.stat}
</span>
</span>
<span className="mt-1 block text-[13px] leading-5 text-pretty text-zinc-500 dark:text-zinc-400">
{layer.detail}
</span>
</span>
</button>
</li>
);
})}
</ol>
</div>
<BlackBox
faces={LAYERS}
value={value}
onValueChange={(id) => setValue(id)}
autoplay={!holding && !picked}
labels={false}
aria-label="Lattice's three parts"
/>
</div>
</div>
);
}
Live preview, examples and props: https://keyframeui.com/components/black-box#black-box-stack-demo