KQ-1561 · CELLULOID/COIL
Celluloid Coil
Pictures become frames on one long strip of film — sprocket holes cut through the base, frame numbers, stock and captions printed on the edge — wound in a loose helix through space in CSS 3D, each frame a plane on the chord between its ends so the strip never tears. The camera rides the strip and follows its turns, so travelling reads as the coil turning past you like a screw: each frame swings round to face you at the gate and curls away round the back; on first view the straight strip winds into its coil on springs.drift. Wheel, drag (1:1 at the gate) and flick travel along it and settle on the nearest frame on springs.glide with the release velocity; Left and Right step frames, Page keys step three, Home and End go to the ends.
Waylight Pictures · location reel
Left and Right step from frame to frame, Page Up and Page Down by three, Home and End go to the ends of the reel.
frame 04 of 10 · glasshouse
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/celluloid-coil
Props
- items
- CelluloidFrame[]
- default defaultCelluloidFrames
- The pictures, one per frame: { src?, alt, caption?, art? }.
- value / defaultValue
- number
- default 0
- The frame in the gate, controlled or initial.
- onValueChange
- (index: number) => void
- default —
- Fires from the drag, wheel, key or click that brought a new frame to the gate.
- twist
- number
- default 0.4
- How much the strip rolls about its own length, 0 to 1.
- frameGap
- number
- default 14
- Film between one picture and the next, px.
- grain
- number
- default 0.35
- Grain, dust and vignette on the pictures, 0 to 1; the grain shimmers only while the strip moves.
- loop
- number
- default 0.6
- How loose the coil is: radius and pitch of the turns, 0 to 1.
- tilt
- number
- default 8
- How far the camera looks down on the coil, degrees (-30 to 30).
- aspect
- number
- default 1.5
- Frame width over height.
- stock
- string
- default "WAYLIGHT 400"
- The film stock printed along the edge.
- stripColor
- string
- default "oklch(from var(--warn) 0.2 0.012 h)"
- The film base colour.
- perspective
- number
- default 1000
- Distance of the eye from the strip, px: smaller is a wider lens.
- wheel
- boolean
- default true
- The wheel travels the strip once the visitor has rested on it or tabbed in, and lets the page scroll at either end.
- height
- number
- default 520
- Height of the stage, px.
- label
- string
- default "Film strip"
- The strip's accessible name.
- disabled
- boolean
- default false
- Stops every gesture and key.
- className
- string
- default —
- Classes for the outer frame.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | CelluloidFrame[] | defaultCelluloidFrames | The pictures, one per frame: { src?, alt, caption?, art? }. |
| value / defaultValue | number | 0 | The frame in the gate, controlled or initial. |
| onValueChange | (index: number) => void | — | Fires from the drag, wheel, key or click that brought a new frame to the gate. |
| twist | number | 0.4 | How much the strip rolls about its own length, 0 to 1. |
| frameGap | number | 14 | Film between one picture and the next, px. |
| grain | number | 0.35 | Grain, dust and vignette on the pictures, 0 to 1; the grain shimmers only while the strip moves. |
| loop | number | 0.6 | How loose the coil is: radius and pitch of the turns, 0 to 1. |
| tilt | number | 8 | How far the camera looks down on the coil, degrees (-30 to 30). |
| aspect | number | 1.5 | Frame width over height. |
| stock | string | "WAYLIGHT 400" | The film stock printed along the edge. |
| stripColor | string | "oklch(from var(--warn) 0.2 0.012 h)" | The film base colour. |
| perspective | number | 1000 | Distance of the eye from the strip, px: smaller is a wider lens. |
| wheel | boolean | true | The wheel travels the strip once the visitor has rested on it or tabbed in, and lets the page scroll at either end. |
| height | number | 520 | Height of the stage, px. |
| label | string | "Film strip" | The strip's accessible name. |
| disabled | boolean | false | Stops every gesture and key. |
| className | string | — | Classes for the outer frame. |