PParable
All components

Image Zoom

Interactive

A hover/press inner-zoom magnifier whose magnified region tracks the pointer inside the image (no lens box), paired with a click-to-open full-screen lightbox that portals to the body with a blurred backdrop, Escape/backdrop-click close, focus trap, and focus return. Under prefers-reduced-motion the zoom-follow is dropped (the static image stays fully legible) and the lightbox opens instantly.

Installation

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

Runs the shadcn CLI — the component source is copied intocomponents/parable/image-zoom.tsx. You own it from there.

Usage

The exact code rendering the preview above.

<div className="flex w-full items-center justify-center p-6">
    <ImageZoom
      className="w-[300px] max-w-full shadow-[0_24px_60px_-30px_rgba(0,0,0,0.9)]"
      zoom={2.6}
      alt="Parable poster — the number 42 inside concentric rings, hover to magnify"
      src={"data:image/svg+xml," + encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 480'><defs><linearGradient id='g' x1='0' y1='0' x2='1' y2='1'><stop offset='0' stop-color='#8b5cf6'/><stop offset='.5' stop-color='#ec4899'/><stop offset='1' stop-color='#f5a623'/></linearGradient><radialGradient id='v' cx='.5' cy='.42' r='.72'><stop offset='0' stop-color='#0f0f10' stop-opacity='0'/><stop offset='1' stop-color='#0f0f10' stop-opacity='.55'/></radialGradient></defs><rect width='640' height='480' fill='#0f0f10'/><rect width='640' height='480' fill='url(#g)' opacity='.92'/><circle cx='320' cy='202' r='120' fill='#0f0f10' fill-opacity='.28'/><circle cx='320' cy='202' r='120' fill='none' stroke='#fff' stroke-opacity='.5' stroke-width='2'/><circle cx='320' cy='202' r='80' fill='none' stroke='#fff' stroke-opacity='.35' stroke-width='1.5'/><text x='320' y='224' font-family='ui-monospace,Menlo,monospace' font-size='76' font-weight='700' fill='#fff' text-anchor='middle'>42</text><text x='320' y='356' font-family='ui-monospace,Menlo,monospace' font-size='27' letter-spacing='9' fill='#fff' fill-opacity='.92' text-anchor='middle'>PARABLE</text><text x='320' y='390' font-family='ui-monospace,Menlo,monospace' font-size='12' letter-spacing='3' fill='#fff' fill-opacity='.6' text-anchor='middle'>HOVER TO MAGNIFY</text><rect x='.5' y='.5' width='639' height='479' fill='url(#v)'/></svg>`)}
    />
  </div>

Props

ImageZoomProps

PropTypeDefaultDescription
src*stringImage source. Used for both the inline frame and the lightbox.
alt*stringAlt text (required). Also names the lightbox dialog for assistive tech.
zoomnumber2Inner-zoom magnification while hovering/pressing the frame. Default `2`.
lightboxbooleantrueWhether clicking the frame opens the full-screen lightbox. Default `true`.
widthnumberIntrinsic pixel width — set with `height` to reserve space (no CLS).
heightnumberIntrinsic pixel height — set with `width` to reserve space (no CLS).
classNamestringExtra classes on the frame element.

npm dependencies

  • motion
  • lucide-react