crucıble

Strata

A pinned scroll section that scrubs an image sequence like a product turntable — pass your own frames or get a seeded faceted gem rendered and cached on the fly, loaded coarse-to-fine behind a hairline progress bar, with neighbour crossfades and captions that fade in at their progress points.

canvaspro

Installation

CLI

npx shadcn@latest add @crucible/strata

Props

PropTypeDefaultDescription
framesstring[]Image sequence to scrub, in playback order (URLs). Frames load progressively coarse-to-fine, so scrubbing works long before the last one lands. When omitted, a seeded procedural turntable renders instead: a faceted gem rotating a full 360°, generated lazily and cached as bitmaps.
pinLengthnumber300Section height as a percentage of the viewport (or the scroller's height). The extra length beyond 100 is the pinned scroll distance that scrubs the sequence.
captionsStrataCaption[][]Overlay captions that fade in and out at their progress points.
scrollerReact.RefObject<HTMLElement | null>the viewportScroll container to track instead of the window. Pass a ref to an overflow-y-auto ancestor; the pin then sizes itself to THAT box.
fit"contain" | "cover""contain"How frames fit the stage.
crossfadebooleantrueBlend between neighbouring frames for sub-frame smoothness.
smoothingnumber0.5Scrub catch-up, 0–1. 0 locks frames 1:1 to the scroll position; higher values ease the turn into place.
frameCountnumber60Frames in the procedural sequence (ignored when frames is set).
seednumber7Seed for the procedural gem's cut (facet count, proportions, sparkle).
colors[string, string]["#e2e8f0", "#93c5fd"]Procedural gem palette as hex: [body, accent] — the crystal's tint and the cool rim light that catches its back facets.
hudbooleantrueShow the small turn readout (degrees, or frame number for custom frames).
idlebooleantrueGentle hover-bob on the procedural gem so the stage never looks frozen. Ignored for custom frames.
labelstringAccessible description of the sequence. When set the canvas is exposed as role="img" with this label; otherwise it is treated as decorative.
dprnumber2Max devicePixelRatio for the stage canvas.
Also accepts all props of Omit< React.ComponentPropsWithoutRef<"section">, "children" > — they pass through to the underlying element.

Honors prefers-reduced-motion with a designed static fallback, pauses offscreen and on hidden tabs, and passes className through.