KQ-1398 · MOON/RING
Moon Ring
Images or generated tiles on a tipped elliptical orbit around a centre object: one phase value drives every moon's position, depth scale, far-side softening and z-order, so moons pass behind the planet and back in front of it, while the ring revolves on its own until a visitor touches it. A drag spins it 1:1 and a release projects the throw, snaps to the nearest moon and lands on springs.drift with the release velocity, so a flick coasts several moons round; a click brings a moon round the shortest way on springs.glide, with an optional whoosh. It is a radio group: the front moon is checked and holds the tab stop, arrow keys bring the neighbours round, and Home and End the first and last.
Coldbrook Observatory · Moons
Season 04
drag, click or use arrows · 6 moons · tilt 20° · drifting 8°/s
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/moon-ring
Props
- items
- { id: string; label: string; src?: string; alt?: string }[]
- default —
- The moons. Short of count, generated tiles fill the ring.
- count
- number
- default 6
- How many moons circle, 3 to 12.
- tilt
- number
- default 20
- How far the orbit tips toward you, degrees: 0 is edge-on, 70 nearly overhead.
- speed
- number
- default 8
- Idle revolution, degrees per second; negative turns the other way, 0 holds still.
- value / defaultValue
- number
- default 0
- The moon at the front. Controlled rings do not drift.
- onValueChange
- (index: number, reason: "drift" | "drag" | "press" | "key") => void
- default —
- A new moon reached the front, with what brought it there.
- lean
- number
- default -8
- The orbit's lean in the picture, degrees.
- depth
- number
- default 0.45
- How much smaller the far side is, 0 to 0.8.
- soften
- number
- default 2
- Blur at the far side of the orbit, px.
- shape
- "circle" | "rounded"
- default "circle"
- Moon shape.
- moonSize
- number
- default —
- Moon size, px. Fits the stage when left out.
- height
- number | string
- default "clamp(9rem, 30cqw, 12.5rem)"
- Height of the stage.
- center
- ReactNode
- default —
- What the moons circle. A lit planet when left out.
- caption
- boolean
- default true
- Name the front moon under the ring.
- label
- string
- default "Orbit"
- Accessible name of the ring.
- sound
- boolean
- default false
- A whoosh when a throw or a long trip brings a moon round.
- paused
- boolean
- default false
- Hold the idle revolution.
- disabled
- boolean
- default false
- No drag, no presses; the moons leave the tab order.
- className
- string
- default —
- Classes for the root (a size container for the stage).
| Prop | Type | Default | Description |
|---|---|---|---|
| items | { id: string; label: string; src?: string; alt?: string }[] | — | The moons. Short of count, generated tiles fill the ring. |
| count | number | 6 | How many moons circle, 3 to 12. |
| tilt | number | 20 | How far the orbit tips toward you, degrees: 0 is edge-on, 70 nearly overhead. |
| speed | number | 8 | Idle revolution, degrees per second; negative turns the other way, 0 holds still. |
| value / defaultValue | number | 0 | The moon at the front. Controlled rings do not drift. |
| onValueChange | (index: number, reason: "drift" | "drag" | "press" | "key") => void | — | A new moon reached the front, with what brought it there. |
| lean | number | -8 | The orbit's lean in the picture, degrees. |
| depth | number | 0.45 | How much smaller the far side is, 0 to 0.8. |
| soften | number | 2 | Blur at the far side of the orbit, px. |
| shape | "circle" | "rounded" | "circle" | Moon shape. |
| moonSize | number | — | Moon size, px. Fits the stage when left out. |
| height | number | string | "clamp(9rem, 30cqw, 12.5rem)" | Height of the stage. |
| center | ReactNode | — | What the moons circle. A lit planet when left out. |
| caption | boolean | true | Name the front moon under the ring. |
| label | string | "Orbit" | Accessible name of the ring. |
| sound | boolean | false | A whoosh when a throw or a long trip brings a moon round. |
| paused | boolean | false | Hold the idle revolution. |
| disabled | boolean | false | No drag, no presses; the moons leave the tab order. |
| className | string | — | Classes for the root (a size container for the stage). |