Magnetic

A wrapper that pulls its child toward the pointer as the pointer gets close.

Installation

npx shadcn@latest add @loomui/magnetic

Usage

import { Magnetic } from "@/components/ui/magnetic"
<Magnetic asChild strength={0.4} radius={90}>
  <button className="rounded-full px-6 py-2.5">Hover near me</button>
</Magnetic>

With asChild the styles and the pull merge onto your own element. The button keeps its hit target instead of gaining a wrapper that changes layout.

The pointer listener sits on window, not on the element. That is deliberate: the pull has to begin before the cursor arrives, or there is no effect to notice.

Use this once per screen

This is a marketing flourish. A page where six things lean at the cursor reads as noise, and every one of them is running a listener. One hero call to action is the right dose.

Props

PropTypeDefaultDescription
strengthnumber0.35How far the child follows, as a fraction of the offset.
radiusnumber80Pixels of slack around the element that count as near.
maxnumber16Largest pull in pixels, whatever the radius says.
asChildbooleanfalseMerge onto the single child instead of wrapping it.
disabledbooleanfalseRender the child with no pull.
classNamestringnoneMerged onto the element.

Any other <div> prop is forwarded.

Accessibility

The pull is skipped entirely under prefers-reduced-motion, and the element snaps back to centre on blur so a keyboard user never lands on a target that has drifted. Movement uses the translate property, which stays on the compositor.