KQ-1644 · REVISION/REEL
Revision Reel
A version history you scrub like footage: dragging the reel's playhead follows the finger 1:1 and dissolves the file's preview from one save into the next by its fractional position, while the deck of version cards above fans open around it — a closed-form bell of extra room, a tilt away from the playhead and a lift for the card at it, all read from one motion value. Released, the playhead is thrown by projection and settles on the nearest version on springs.snap with the release velocity; Restore lifts the chosen card on snap while the host saves, then a new newest version is born where it was, carried to the top of the stack on springs.glide and set down on snap. The reel is a slider — Left and Right step, Page keys jump, Home and End, Enter restores, C marks two versions to compare side by side, D downloads, Escape closes the comparison — and becomes a listbox of versions at phone widths.
Waylight launch poster
12 versions · 4.4 MB
Left and Right step through versions, Page Up and Page Down jump five, Home and End go to the first and latest. Enter restores, C marks a version and a second mark compares, D downloads, Escape closes the comparison.
v12 of 12 · Ines · 2 h ago · Final type pass
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/revision-reel
Props
- versions / defaultVersions
- RevisionVersion[]
- default — / defaultRevisionVersions
- Every save: { id, author, at, size, note, preview? }, shown oldest to newest by time. A missing preview gets a placeholder card.
- onVersionsChange
- (versions: RevisionVersion[]) => void
- default —
- Fires with the whole list when a restore adds a version.
- value / defaultValue
- string
- default — / the newest
- The version at the playhead, by id, controlled or initial.
- onValueChange
- (id: string) => void
- default —
- Fires from the drag, tap or key that moved the playhead to a new version.
- onRestore
- (version) => void | Promise<unknown>
- default —
- Restore (or Enter). Return a promise to hold the card up while it saves; a rejection shows a failed card with Try again.
- onCompare
- (older, newer) => void
- default —
- Two versions were marked and opened side by side, older first.
- onDownload
- (version) => void
- default —
- Download (or D) for the version at the playhead.
- status
- "ready" | "loading" | "error"
- default "ready"
- Loading shows placeholder cards and a skeleton reel; error shows Try again.
- onRetry
- () => void
- default —
- Try again was pressed after the history failed to load.
- now
- number
- default defaultRevisionNow
- The moment ages count from, in ms; never read from the clock during render.
- author
- string
- default "You"
- The name a restore is saved under.
- fileName
- string
- default "Waylight launch poster"
- The file's name, shown in the header and naming the surface.
- reelStyle
- "film" | "ticks" | "beads"
- default "film"
- How the reel is drawn: film frames with sprocket holes, ticks placed by time with day labels, or beads on a thread.
- previewFit
- "fit" | "fill" | "width"
- default "fit"
- How the preview sits in its pane: whole and letterboxed, cropped to fill, or fit to width and scrolled.
- accent
- string
- default "var(--accent-bright)"
- Playhead, marks, the current card and Restore, any CSS colour.
- height
- number
- default 540
- Height of the surface in px.
- disabled
- boolean
- default false
- Nothing can be scrubbed, marked, restored or downloaded.
- className
- string
- default —
- Classes for the outer surface.
| Prop | Type | Default | Description |
|---|---|---|---|
| versions / defaultVersions | RevisionVersion[] | — / defaultRevisionVersions | Every save: { id, author, at, size, note, preview? }, shown oldest to newest by time. A missing preview gets a placeholder card. |
| onVersionsChange | (versions: RevisionVersion[]) => void | — | Fires with the whole list when a restore adds a version. |
| value / defaultValue | string | — / the newest | The version at the playhead, by id, controlled or initial. |
| onValueChange | (id: string) => void | — | Fires from the drag, tap or key that moved the playhead to a new version. |
| onRestore | (version) => void | Promise<unknown> | — | Restore (or Enter). Return a promise to hold the card up while it saves; a rejection shows a failed card with Try again. |
| onCompare | (older, newer) => void | — | Two versions were marked and opened side by side, older first. |
| onDownload | (version) => void | — | Download (or D) for the version at the playhead. |
| status | "ready" | "loading" | "error" | "ready" | Loading shows placeholder cards and a skeleton reel; error shows Try again. |
| onRetry | () => void | — | Try again was pressed after the history failed to load. |
| now | number | defaultRevisionNow | The moment ages count from, in ms; never read from the clock during render. |
| author | string | "You" | The name a restore is saved under. |
| fileName | string | "Waylight launch poster" | The file's name, shown in the header and naming the surface. |
| reelStyle | "film" | "ticks" | "beads" | "film" | How the reel is drawn: film frames with sprocket holes, ticks placed by time with day labels, or beads on a thread. |
| previewFit | "fit" | "fill" | "width" | "fit" | How the preview sits in its pane: whole and letterboxed, cropped to fill, or fit to width and scrolled. |
| accent | string | "var(--accent-bright)" | Playhead, marks, the current card and Restore, any CSS colour. |
| height | number | 540 | Height of the surface in px. |
| disabled | boolean | false | Nothing can be scrubbed, marked, restored or downloaded. |
| className | string | — | Classes for the outer surface. |