Images on a tilted 3D ring. Drag or flick it and it settles on the nearest image; click one to bring it round to the front.
pnpm dlx shadcn@latest add @latheui/orbit-galleryPart of Lathe Pro. Set up your project once with your license key: npx latheui init --key <key>. See Lathe Pro.
Orbit Gallery is part of Lathe Pro
The preview is live and free to try. The source, the install and every assembly come with Pro: $79 once, with lifetime updates.
Depends on
Also accepts native div attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
| items* (required) | { src: string; alt: string; title?: string; caption?: string }[] | — | The images, in order around the ring. |
| label* (required) | string | — | Accessible name for the gallery. |
| index | number | — | Controlled index of the item at the front. Changing it turns the ring the short way. |
| defaultIndex | number | 0 | Item at the front to begin with. |
| onIndexChange | (index: number) => void | — | Called as a new item reaches the front. |
| itemWidth | number | 180 | Width of an item in px. |
| aspect | number | 4 / 5 | Width divided by height. |
| spacing | number | 28 | Space between neighbours along the ring, in px. Sets the ring's size. |
| radius | number | from the items | Ring radius in px, when you want a fixed size. |
| tilt | number | -10 | Degrees the ring leans. Negative looks down onto it. |
| perspective | number | 1400 | Camera distance in px. Lower is more dramatic. |
| autoRotate | number | 0 | Degrees per second the ring turns on its own. |
| sensitivity | number | 0.28 | Degrees turned per pixel dragged. |
| fade | number | 0.7 | How far items behind the front fade, from 0 to 1. |
| showCaption | boolean | true | Shows the front item's title and caption under the ring. |
| curve | Curve | gentle spring | How the ring settles. Any curve from the Animation Lab; springs carry the speed of a flick. |
| duration | number | — | Milliseconds, for curves that are not springs. |
| renderItem | (item, { active }) => ReactNode | — | Draw an item yourself instead of the image. |
<OrbitGallery label="Albums" items={albums} itemWidth={140} aspect={1} tilt={-18} autoRotate={14} /><OrbitGallery label="Work" items={items} curve={{ type: "spring", stiffness: 160, damping: 11 }} /><OrbitGallery
label="Team"
items={people}
renderItem={(person, { active }) => (
<div className={active ? "bg-primary text-primary-foreground" : "bg-muted"}>{person.title}</div>
)}
/>