Components

3D Carousel

3d x rotate

3D rotating carousel with perspective transforms. From Cult UI.

carousel3drotatecultui
1
2
3
4
5

Code

carousel-3d.tsx
"use client";
import { useState } from "react";

/* Each face is rotated onto a cylinder and pushed out by translateZ, so the
   whole ring only needs one rotateY to spin. radius ≈ (width / 2) / tan(180/n). */
export function Carousel3D({ faces, radius = 150 }: { faces: string[]; radius?: number }) {
  const [i, setI] = useState(0);
  const step = 360 / faces.length;
  return (
    <div className="grid place-items-center gap-4">
      <div className="relative h-32 w-56" style={{ perspective: "900px" }}>
        <div className="absolute inset-0 transition-transform duration-700 ease-out"
          style={{ transformStyle: "preserve-3d", transform: `rotateY(${-i * step}deg)` }}>
          {faces.map((c, n) => (
            <div key={c} className="absolute inset-0 grid place-items-center rounded-xl text-sm font-semibold text-white"
              style={{ background: c, transform: `rotateY(${n * step}deg) translateZ(${radius}px)`, backfaceVisibility: "hidden" }}>
              {n + 1}
            </div>
          ))}
        </div>
      </div>
      <div className="flex gap-2">
        <button onClick={() => setI((p) => p - 1)} className="rounded-lg border border-border px-3 py-1.5 text-sm">‹ Prev</button>
        <button onClick={() => setI((p) => p + 1)} className="rounded-lg border border-border px-3 py-1.5 text-sm">Next ›</button>
      </div>
    </div>
  );
}

Use it in another build

Paste the code into a component file, keep your project tokens (background, brand, radius) and it themes itself. Or tell Claude Code: “add the 3D Carousel component and wire it to my accent.”