Sculpture orbit
3DA shared sculpture viewer with pointer rotation, touch-friendly navigation and complete keyboard controls.
Try it
Add to your project
npx shadcn@latest add https://luv-jeri.github.io/cojeev-ui/r/sculpture-orbit.jsonThe command includes the component’s shared dependencies. Your project keeps editable source files.
Include the complete example
This example also composes glyph-sculpture, dither-sculpture, ink-sculpture, button, card, input, label, native-select, slider, switch, typography. Install its parts together:
npx shadcn@latest add https://luv-jeri.github.io/cojeev-ui/r/glyph-sculpture.json https://luv-jeri.github.io/cojeev-ui/r/dither-sculpture.json https://luv-jeri.github.io/cojeev-ui/r/ink-sculpture.json https://luv-jeri.github.io/cojeev-ui/r/sculpture-orbit.json https://luv-jeri.github.io/cojeev-ui/r/button.json https://luv-jeri.github.io/cojeev-ui/r/card.json https://luv-jeri.github.io/cojeev-ui/r/input.json https://luv-jeri.github.io/cojeev-ui/r/label.json https://luv-jeri.github.io/cojeev-ui/r/native-select.json https://luv-jeri.github.io/cojeev-ui/r/slider.json https://luv-jeri.github.io/cojeev-ui/r/switch.json https://luv-jeri.github.io/cojeev-ui/r/typography.jsonUsing sculpture orbit
Render a sculpture through children({turn,pitch,zoom,interacting}). Pass paused={interacting} to hold its optional rotation while manipulating it.
Omit value for internal state, or pass value/onValueChange for controlled orientation. defaultValue initializes internal state. Reset returns to turn=0, pitch=0, zoom=1.
Drag with a mouse to turn and tilt. Touch swipes rotate horizontally while vertical movement keeps page scrolling. Zoom uses a native slider, with turn/tilt and reset buttons.
disabled prevents pointer and keyboard input. Turn wraps around; pitch is bounded to ±80°, and zoom to 0.6–1.15.
API
Compose the exported parts below. The prop types are read from the React source during the registry build.
Native element or underlying primitive props are inherited where declared, including accessible labels, event handlers and refs.
SculptureOrbitProps
| Prop | Type | Required |
|---|---|---|
children | (view: SculptureView & { interacting: boolean }) => React.ReactNode | Yes |
value | SculptureView | No |
defaultValue | Partial<SculptureView> | No |
onValueChange | (view: SculptureView) => void | No |
disabled | boolean | No |
label | string | No |
Accessibility
The viewport is labelled and keyboard focusable. Arrow keys rotate, Shift uses larger steps, +/− zoom and Home resets.
Explicit view controls work with reduced motion and shared motion disabled. Place essential content outside the decorative sculpture.
States and appearance
For conditional content, keep a MotionPresence boundary around keyed MotionSurface children. The shared entrance and exit states work with native primitives and respect your motion preference.
Try pointer and keyboard interaction, and switch the appearance control in the navigation to compare light and dark mode. Motion respects reduced motion preferences.