caliper uidocs

Magnetic

Free

Wraps one button or link so it leans toward the pointer as it comes near, up to 8px, and settles back when the pointer leaves.

Installs components/ui/magnetic.tsxDepends on none beyond ReactMotion honours reduced motion
pnpm dlx shadcn@latest add https://caliperui.site/r/magnetic.json

When to use #

Use it for

  • The one or two actions you want people to notice, such as a hero button.
  • Marketing and onboarding surfaces where a little life helps.

Skip it when

  • Dense toolbars and tables; many things leaning at once is noise.
  • Touch and keyboard: it does nothing there, so nothing may depend on it.

Decisions #

Why it is built this way, so you know what to keep when you change your copy.

Behaviour

Only the wrapper moves
The control inside keeps its own press, focus ring and hit area, so activation never changes. The lean is a follow with a soft settle, not a spring that overshoots.
Fine pointers only
Touch, keyboard focus and reduced motion get no lean at all. Nothing important may depend on it.

Usage

Wrap one child
A lean larger than 8px starts to feel like the button is running away, so the limit is part of the part.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/magnetic.json

Adds its 2 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { Button } from "@/components/ui/button"
import { Magnetic } from "@/components/ui/magnetic"

export function MagneticDemo() {
  return (
    <div className="flex flex-wrap items-center justify-center gap-8 px-4 py-10">
      <Magnetic><Button size="lg">Start free</Button></Magnetic>
      <Magnetic><Button size="lg" variant="secondary">Read the docs</Button></Magnetic>
      <Magnetic><Button size="lg" variant="ghost">View on GitHub</Button></Magnetic>
    </div>
  );
}

API reference #

Magnetic

component

Also accepts the native props of its root element and a ref.

PropTypeDefaultDescription
strengthnumber0.28How much of the distance to the pointer it follows. 0.28 is a gentle lean.
maxnumber8The most it moves, in pixels.
reachnumber40How far past its edge the pointer starts to pull, in pixels.

Accessibility #

It is built on native elements, so roles and focus come from the browser.

No custom key handling; Tab and the native activation keys do the work.

Motion #

It checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.