crucıble

Sightline

A pinned scroll section where an inline media card grows to full-bleed through a shaped SVG aperture (rounded, circle, pill or any custom path) — corners relax to square, a scrim rises, and the caption rides the aperture's edge before settling as an overlay. Reduced motion skips the pin for a static crossfade.

motionfree

Installation

CLI

npx shadcn@latest add @crucible/sightline

Manual — install dependencies, then copy the source

npm install motion

Props

PropTypeDefaultDescription
childrenReact.ReactNodeMedia shown through the aperture. Any node works (an <img>, <video>, a gradient, a UI mock); it is stretched to fill the full-bleed frame. Takes precedence over src. When neither is given a seeded procedural plate (layered dusk ridgelines) renders.
srcstringImage or video URL (videos are detected by extension and play muted + looped).
altstring""Alt text for src images. Leave empty for decorative media.
shapeSightlineShape"rounded"Aperture outline the media grows through.
pathstringan arched windowCustom aperture outline for shape="path": an SVG path d string drawn in a 0–1 unit box (e.g. "M0.5 0 L1 1 L0 1 Z"). It scales from the center, keeping its aspect.
pinLengthnumber220Section height as a percentage of the viewport (or the scroller's height); the extra length is the pinned scroll distance.
captionReact.ReactNodeCaption that rides the aperture's bottom edge, then settles as an overlay once full-bleed.
dimnumber0.6Maximum scrim darkness laid over the media as it reaches full-bleed (0–1).
radiusnumber28Corner radius of the starting card in px (rounded shape).
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.
surfacestring"#0a0a0a"Surface color around the card. Only painted in the reduced-motion crossfade (the card's surround fades out to reveal the full-bleed media).
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, and passes className through.