"use client";
import ParallaxPortal, {
ParallaxPortalLayer,
} from "@/components/ui/parallax-portal";
/** A small seeded generator, so every render draws the same shapes. */
function seeded(seed: number) {
let a = seed;
return () => {
a = (a + 0x6d2b79f5) | 0;
let t = Math.imul(a ^ (a >>> 15), 1 | a);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
function Painting({ seed, className }: { seed: number; className?: string }) {
const rand = seeded(seed);
const shapes = Array.from({ length: 7 }, () => ({
x: rand() * 100,
y: rand() * 70,
r: 8 + rand() * 22,
a: rand(),
}));
return (
<div
className={`border-[6px] border-[color-mix(in_oklab,var(--color-ink)_78%,var(--color-surface))] bg-surface p-2 shadow-[var(--shadow-float)] ${className ?? ""}`}
>
<svg
viewBox="0 0 100 70"
className="h-full w-full bg-[color-mix(in_oklab,var(--color-accent)_14%,var(--color-surface))]"
aria-hidden="true"
>
{shapes.map((s, i) => (
<circle
key={i}
cx={s.x}
cy={s.y}
r={s.r}
fill={
i % 3 === 0
? "var(--color-accent)"
: i % 3 === 1
? "var(--color-ink)"
: "var(--color-accent-strong)"
}
opacity={0.25 + s.a * 0.6}
/>
))}
<path
d={`M0 ${50 + rand() * 10} Q50 ${30 + rand() * 20} 100 ${48 + rand() * 12} V70 H0 Z`}
fill="var(--color-ink)"
opacity="0.8"
/>
</svg>
</div>
);
}
const GALLERY_WALL =
"color-mix(in oklab, var(--color-surface) 88%, var(--color-accent) 12%)";
const GALLERY_WALLS = {
back: (
<div
className="absolute inset-0 flex flex-col items-center justify-center gap-3"
style={{ background: GALLERY_WALL }}
>
<Painting seed={11} className="h-[46%] w-[40%]" />
<div className="rounded-[var(--radius-2)] bg-surface px-2 py-1 text-[9px] font-semibold text-ink-soft shadow-[var(--shadow-tile)]">
Room 3 · Light studies, 2026
</div>
</div>
),
left: (
<div
className="absolute inset-0 flex items-center justify-around px-8"
style={{ background: GALLERY_WALL }}
>
<Painting seed={4} className="h-[34%] w-[26%]" />
<Painting seed={21} className="h-[40%] w-[30%]" />
</div>
),
right: (
<div
className="absolute inset-0 flex items-center justify-around px-8"
style={{ background: GALLERY_WALL }}
>
<Painting seed={32} className="h-[40%] w-[30%]" />
<Painting seed={8} className="h-[30%] w-[24%]" />
</div>
),
floor: (
<div className="absolute inset-0 bg-[repeating-linear-gradient(90deg,color-mix(in_oklab,var(--color-ink)_14%,var(--color-surface))_0_46px,color-mix(in_oklab,var(--color-ink)_22%,var(--color-surface))_46px_48px)]">
<div className="absolute inset-0 bg-[linear-gradient(to_bottom,transparent,color-mix(in_oklab,white_18%,transparent)_55%,transparent)]" />
</div>
),
ceiling: (
<div className="absolute inset-0 bg-surface-muted">
<div className="absolute inset-x-[18%] top-[20%] h-[18%] rounded-[var(--radius-4)] bg-surface shadow-[0_0_40px_color-mix(in_oklab,white_70%,transparent)]" />
<div className="absolute inset-x-[18%] top-[58%] h-[18%] rounded-[var(--radius-4)] bg-surface shadow-[0_0_40px_color-mix(in_oklab,white_70%,transparent)]" />
</div>
),
};
function Bench() {
return (
<svg viewBox="0 0 200 60" className="w-[200px]" aria-hidden="true">
<rect
x="0"
y="8"
width="200"
height="16"
rx="3"
fill="color-mix(in oklab, var(--color-ink) 70%, var(--color-accent))"
/>
<rect x="14" y="24" width="10" height="36" fill="var(--color-ink)" />
<rect x="176" y="24" width="10" height="36" fill="var(--color-ink)" />
</svg>
);
}
function Sculpture() {
return (
<svg viewBox="0 0 90 190" className="w-[90px]" aria-hidden="true">
<path
d="M45 6 C75 20 70 60 48 78 C30 94 70 104 60 124 L30 124 C20 104 42 94 26 70 C12 48 20 14 45 6 Z"
fill="var(--color-accent)"
/>
<rect
x="10"
y="124"
width="70"
height="66"
fill="var(--color-surface)"
stroke="var(--color-line-strong)"
/>
</svg>
);
}
function Plant() {
return (
<svg viewBox="0 0 160 220" className="w-[150px]" aria-hidden="true">
{[-50, -25, 0, 25, 50, -70, 70].map((a, i) => (
<path
key={i}
d="M80 150 C70 110 60 70 80 20 C100 70 90 110 80 150 Z"
transform={`rotate(${a} 80 150)`}
fill={
i % 2
? "color-mix(in oklab, var(--color-accent-strong) 70%, var(--color-ink))"
: "var(--color-accent-strong)"
}
/>
))}
<path
d="M50 150 H110 L102 220 H58 Z"
fill="color-mix(in oklab, var(--color-ink) 80%, var(--color-surface))"
/>
</svg>
);
}
export default function ParallaxPortalGalleryDemo() {
return (
<div className="flex w-full items-center justify-center bg-canvas p-10">
<ParallaxPortal
label="A small gallery room behind the page"
walls={GALLERY_WALLS}
depth={560}
className="h-[380px] w-full max-w-xl"
>
<ParallaxPortalLayer depth={420} x={0.26}>
<Sculpture />
</ParallaxPortalLayer>
<ParallaxPortalLayer depth={230} x={0.58}>
<Bench />
</ParallaxPortalLayer>
<ParallaxPortalLayer depth={170} x={0.8} y={0} anchor="top">
<div className="flex flex-col items-center">
<span className="h-16 w-px bg-ink-faint" />
<span className="h-5 w-12 rounded-t-full bg-ink" />
<span className="h-3 w-16 rounded-full bg-[radial-gradient(closest-side,color-mix(in_oklab,white_90%,var(--color-accent)),transparent)]" />
</div>
</ParallaxPortalLayer>
<ParallaxPortalLayer depth={-90} x={0.06} y={1.06}>
<Plant />
</ParallaxPortalLayer>
<ParallaxPortalLayer depth={-60} x={0.88} y={0.2} anchor="center">
<div className="w-[150px] rounded-[var(--radius-tile)] border border-line bg-surface p-3 shadow-[var(--shadow-window)]">
<p className="text-[10px] font-bold uppercase tracking-wider text-ink-faint">
Now showing
</p>
<p className="text-sm font-bold text-ink">Light studies</p>
<p className="text-xs text-ink-soft">Twelve works on paper</p>
</div>
</ParallaxPortalLayer>
</ParallaxPortal>
</div>
);
}