Portal Peeler

ProInteractivitypowered by @vectorvesper/motion

A peel-away portal that reveals an underlay as the pointer drags across it. Brush size, spacing, heal rate and viscosity control how quickly and how thickly the surface closes back over itself.

Portal Peeler

Included with membership

Members install Portal Peeler with one command and get the full source, the usage code and the Framer remix, licensed for client work. One membership covers the whole library and the CLI.

When to use it

Two layers where the point is that one is hidden behind the other — a before and after, a reveal, a second image under the first. It takes both layers as children rather than image URLs, so either side can be any markup you like, not only a picture.

  • Give both layers the same size and let the wrapper set it — a mismatch shows as a hard edge where the hole should be.
  • Make the two layers clearly different. The effect is about the contrast between them, so two similar photographs read as a smudge.
  • Lower healRate when you want the hole to linger, and raise it when the top layer should close up behind the pointer.

Avoid:

  • Do not put anything interactive in the underlay. It sits behind a mask and is not reliably clickable.
  • Do not pass an image URL — this component takes rendered layers, not sources. There is no src prop.
  • Do not rely on it to communicate anything essential; whatever is underneath is only ever partly visible.

Props

Two layers stacked, where the cursor rubs a hole through the top one to reveal what is underneath. The hole closes again behind you, like frost re-forming on glass. Both layers are your own markup.

<PortalPeeler />

The stack. Fills its container, so give the parent a size.

PropTypeDefaultDescription
children*React.ReactNode—The top layer — what gets rubbed away.
underlay*React.ReactNode—The layer beneath, revealed through the hole.
sizenumber60Radius of the hole the cursor opens, in pixels.
spacingnumber10Distance between sample points along the cursor's path. Lower gives a smoother trail at more cost; higher leaves a dotted one on fast movement.
healRatenumber0.04How quickly the hole closes behind you. Low by default, so the trail lingers — raise it to have the top layer snap back.
viscositynumber12How thick the top layer behaves. Higher makes the hole's edges cling and drag rather than cutting cleanly.
classNamestring""Applied to the outer wrapper.
topLayerClassNamestring""Applied to the top layer's container.
underlayClassNamestring""Applied to the underlay's container.
The hole only opens where the cursor goes — nothing moves on its own, so there is no ambient motion to suppress. It has no explicit reduced-motion state.
Cost follows the trail: lowering spacing adds sample points on every pointer move. If it feels heavy on a large surface, raise spacing before lowering size.
Client component. It reads the pointer and draws the mask per frame, so it has to run in the browser.
Back to all components