PParable
All components

Image Reveal

Visual Effects

A 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

Abstract violet-to-ember gradient artwork

Installation

npx shadcn@latest add https://parable-three.vercel.app/r/image-reveal.json

Runs 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">

PropTypeDefaultDescription
src*stringImage source URL.
alt*stringAlt text. Required — pass "" only for decorative imagery.
aspectstring"16/9"CSS aspect-ratio for the frame, e.g. "16/9" or "4/5". Prevents layout shift.
directionRevealDirection"up"Which way the curtain wipe travels as it uncovers the image.
roundedstring"1rem"Border radius for the frame, as any CSS length (e.g. "1rem", "9999px").
amountnumber0.35Fraction of the frame that must be visible before revealing (0–1).
oncebooleantrueReveal only the first time it scrolls into view.
durationnumber1.05Reveal duration in seconds.
loading"lazy" | "eager""lazy"`loading` hint forwarded to the underlying <img>.

npm dependencies

  • motion