Skip to content
WANCRAFT

H.293D & Experimental

Rotating Product Stage

A CSS 3D product stage with drag-to-rotate inertia, keyboard turns and per-face lighting presets.

ReactCSSTailwindadvanced

Overview

Rotating Product Stage presents a labelled product box in pure CSS 3D — no WebGL. Drag with pointer capture and release to flick it with friction, or focus the stage and turn it with the arrow keys. Shading is real: each face's brightness and specular highlight are computed from the light direction and the current rotation (Lambert + Blinn), and written to CSS variables inside a requestAnimationFrame loop that sleeps whenever nothing moves, offscreen, or in a background tab. Studio, warm and night presets change the environment, material, ink and light colour together. Faces can be replaced with your own content.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/rotating-product-stage.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/rotating-product-stage.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/rotating-product-stage.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
1 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { RotatingProductStage } from "@/components/ui/rotating-product-stage";

export function RotatingProductStageExample() {
  return (
    <div className="relative h-[480px] w-full overflow-hidden rounded-2xl">
      <RotatingProductStage />
    </div>
  );
}

03Props

PropTypeDefaultDescription
titlestring"Model 01"Product name on the front face and in the accessible name.
brandstring"Wancraft"Brand mark printed on the faces.
descriptionstring"A matte compact speaker…"Read by assistive technology as the product image description.
lighting"studio" | "warm" | "night""studio"Environment, material and light preset.
autoRotatebooleantrueTurn slowly while idle; pauses for 2.5s after interaction.
autoRotateSpeednumber14Auto-rotation speed in degrees per second.
inertiabooleantrueKeep spinning after a flick, with friction.
perspectivenumber1100CSS perspective in px; lower is more dramatic.
sensitivitynumber0.4Degrees per pixel dragged.
accentstring"#FF7448"Status light, details and focus ring.
showControlsbooleantrueReset button, lighting label and interaction hint.
initialRotation{ x: number; y: number }{ x: -16, y: -32 }Resting angle in degrees (read on mount).
facesPartial<Record<"front" | "back" | "left" | "right" | "top" | "bottom", ReactNode>>—Replace the content of individual faces.

04Features

  • 01Pure CSS 3D transforms — no WebGL or canvas
  • 02Per-face Lambert diffuse + Blinn specular from the live rotation
  • 03Drag with pointer capture, flick inertia and tilt clamping
  • 04Arrow-key turns, Shift for quarter turns, Home to reset
  • 05Scales with its container via container query units
  • 06Animation loop sleeps when idle, offscreen or in a hidden tab
motion · continuousmotion · tweeninput · draginput · keyboardinput · focusinput · click

05Accessibility

  • The stage is a focusable group with an accessible name and a description that includes the interaction instructions.
  • The product is exposed as role="img" with a descriptive aria-label; face artwork is aria-hidden.
  • Arrow keys rotate (Shift for 90°), Home resets; a native Reset view button is also provided.
  • With prefers-reduced-motion the product rests at a static angle: no auto-rotation, no inertia, keyboard turns are instant.
  • Vertical page scrolling still works on touch (touch-action: pan-y); horizontal drags rotate.

06Limitations

  • CSS 3D faces are flat planes: rounded or curved products need custom face content to suggest form.
  • Lighting is an approximation computed per face, not per pixel.