Let people grab a product and spin it. SpinViewer turns an ordered sequence of frames into a 360° object you drag with a mouse or touch. It preloads every frame so the spin never stalls on a load, idles with a slow auto-rotate until the first grab, and shows a "drag to rotate" hint for first-timers. Use it for a product hero, an app device shot, or a portfolio centerpiece.
CLI Manual
pnpm dlx shadcn@latest add "https://godui.design/r/lab/spin-viewer.json"import { SpinViewer } from "@/components/godui/spin-viewer" ; Pass an ordered array of frame URLs, typically 24 to 48 photos or renders taken a
few degrees apart around the object:
const frames = Array . from (
{ length : 36 },
( _ , i ) => `/product/frame- ${ String ( i ). padStart ( 2 , "0" ) } .webp` ,
);
< SpinViewer frames = { frames } className = "size-72" />; Idle auto-rotate until grabbed, tune the drag feel, or reverse the direction:
< SpinViewer frames = { frames } autoRotate autoRotateSpeed = { 16 } />
< SpinViewer frames = { frames } sensitivity = { 4 } />
< SpinViewer frames = { frames } reverse hint = { false } /> Vertical page scroll still works over the viewer (touch-action: pan-y), and
auto-rotate is disabled under prefers-reduced-motion. Dragging always works.
Prop Type Default Description framesstring[]none Ordered image URLs, one per rotation frame. autoRotatebooleanfalseSpin on its own until the first interaction. autoRotateSpeednumber12Auto-rotate speed, in frames per second. sensitivitynumber6Pixels of horizontal drag per frame step. reversebooleanfalseReverse the drag/spin direction. initialFramenumber0Frame index to start on. hintbooleantrueShow the "drag to rotate" hint until first interaction. labelstring"360-degree view…"Accessible label for the viewer.
All other div props are forwarded to the root element.