StickyButton

A magnetic button whose body and label are pulled toward the cursor from a wide field, with parallax depth and tilt.

StickyButton grabs the cursor before it even arrives. Once the pointer comes within radius pixels of the button's edge, the body is pulled toward it, and the pull gets stronger the closer you get. The label drifts a little further toward the cursor on a looser spring, staying inside the button's padding, so the two layers separate like a parallax card, while the body tilts toward the cursor and a soft spotlight follows it across the face.

Preview

Props

Install

Add the item with the shadcn CLI.

npx shadcn@latest add @evilbuttons/sticky

Usage

import StickyButton from "@/components/evil-buttons/sticky";

export function ButtonDemo() {
  return <StickyButton>Launch</StickyButton>;
}

Variants

Clingy

A wider field and a stronger pull make the button chase the cursor from far away.

Subtle

A tight field with no tilt, for a gentle magnetic nudge.

Props

The component spreads native button props and forwards its ref to the button.

PropTypeDefaultDescription
childrenReact.ReactNode-The button label or content.
radiusnumber120Distance in px beyond the button's edge where the pull starts.
strengthnumber0.45How far the body follows the cursor, as a fraction of the cursor offset.
parallaxnumber0.35How far the label drifts inside the body, from 0 (fixed to the body) to 1 (the edge of its padding).
tiltnumber8Maximum tilt in degrees while the body is pulled.
classNamestring-Extra classes passed to the button.

Notes

  • The pull eases out with a smoothstep curve, so it is at full strength over the button and fades to zero at the edge of the field instead of snapping.
  • Distance is measured from a wrapper that never moves, so the button being pulled doesn't change where the field is.
  • Everything runs on motion values and springs, with no React re-renders on pointer move.
  • Touch input and prefers-reduced-motion skip the magnetic effect, and so does a disabled button.

Registry

The registry item includes components/evil-buttons/sticky.tsx and installs motion, clsx, and tailwind-merge as dependencies. The component imports cn from @/lib/utils, matching the project alias in components.json.

Search docs

Jump to a button documentation page