Image Reveal
Visual EffectsA scroll-triggered curtain wipe that uncovers an image via an animating clip-path inset, a 1.1→1 overscan, and a single diagonal sheen sweep, fired once on scroll-into-view. Under prefers-reduced-motion the image is shown immediately at full size with no wipe, scale, or sheen.
Inspired by Skiper UI — image reveal (pattern); upstream interaction genre — independently built, not affiliated. Attribution policy
Installation
npx shadcn@latest add https://parable-three.vercel.app/r/image-reveal.jsonRuns the shadcn CLI — the component source is copied intocomponents/parable/image-reveal.tsx. You own it from there.
Usage
The exact code rendering the preview above.
<div className="flex w-full items-center justify-center bg-[#0f0f10] p-6">
<ImageReveal
src={`data:image/svg+xml,${encodeURIComponent(
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 800 450'><defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'><stop offset='0' stop-color='#8b5cf6'/><stop offset='0.55' stop-color='#ec4899'/><stop offset='1' stop-color='#f5a623'/></linearGradient></defs><rect width='800' height='450' fill='#0f0f10'/><rect width='800' height='450' fill='url(%23g)' opacity='0.92'/><circle cx='610' cy='120' r='150' fill='#22d3ee' opacity='0.35'/><circle cx='170' cy='360' r='120' fill='#8b5cf6' opacity='0.45'/></svg>"
)}`}
alt="Abstract violet-to-ember gradient artwork"
aspect="16/9"
direction="up"
rounded="1rem"
className="w-full max-w-sm shadow-2xl ring-1 ring-white/10"
/>
</div>Props
ImageRevealProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">
| Prop | Type | Default | Description |
|---|---|---|---|
| src* | string | — | Image source URL. |
| alt* | string | — | Alt text. Required — pass "" only for decorative imagery. |
| aspect | string | "16/9" | CSS aspect-ratio for the frame, e.g. "16/9" or "4/5". Prevents layout shift. |
| direction | RevealDirection | "up" | Which way the curtain wipe travels as it uncovers the image. |
| rounded | string | "1rem" | Border radius for the frame, as any CSS length (e.g. "1rem", "9999px"). |
| amount | number | 0.35 | Fraction of the frame that must be visible before revealing (0–1). |
| once | boolean | true | Reveal only the first time it scrolls into view. |
| duration | number | 1.05 | Reveal duration in seconds. |
| loading | "lazy" | "eager" | "lazy" | `loading` hint forwarded to the underlying <img>. |
npm dependencies
- motion