Skip to content
Template Empire / components

Search components

10 results

Browse components

Magnetic Button

A free magnetic button for React and Next.js: an animated button that leans toward the cursor and springs back home.

  • Automated axe check
  • Reduced-motion tested
  • SSR build verified
  • Motion
  • 1 runtime package

Magnetic Button is a free animated button for React and Next.js, built with Motion and styled with Tailwind. Within 100 pixels of the control the whole pill translates toward your cursor by the pointer offset times a configurable strength, capped at 16 pixels, while the label inside leans an extra 25 percent for parallax depth. Move away and both spring home with a soft overshoot, pressing scales the control to 0.96 while active, and hovering brightens the background or border over 150ms.

The pull runs on Motion spring values, so pointer tracking never schedules a React render, and the hover hit-target is a static wrapper so the control can never escape the pointer. It renders a real anchor when you pass href and a real button otherwise, in solid and outline variants. The effect is gated to fine pointers with no reduced-motion preference: on touch devices or with reduced motion enabled the control is completely static with standard hover and focus colour states, and keyboard focus never triggers displacement.

Customise

Component settings update the preview and generated code together.

Content

Appearance

Motion

0.3

Behaviour

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/btn-magnetic

Usage

import { BtnMagnetic } from "@/components/btn-magnetic";

export default function Page() {
  return (
    <div className="flex items-center gap-2">
      <BtnMagnetic href="/pricing">See pricing</BtnMagnetic>
      <BtnMagnetic variant="outline" strength={0.4}>
        Watch the demo
      </BtnMagnetic>
    </div>
  );
}

Props

PropTypeDefaultDescription
childrenReactNoderequiredButton label.
hrefstringundefinedRenders a real anchor when set; otherwise a real button.
variant"solid" | "outline""solid"Visual variant: inverted solid pill (foreground background, background text) or outline.
strengthnumber0.3Fraction of the pointer offset the control translates by, always capped at 16px.
classNamestringundefinedAdditional classes merged onto the control.

Customisation

Magnetic Button declares no tokens of its own. The solid variant paints with the inverted foreground and background semantic tokens, the outline variant with border and ring, so retheming those tokens rethemes both variants with the rest of your page. Tune the pull with the strength prop and restyle the pill from the className prop:

<BtnMagnetic href="/pricing" strength={0.5} className="px-8 text-base">
  See pricing
</BtnMagnetic>

/* retheme the control via the semantic tokens */
:root {
  --foreground: oklch(0.97 0.01 280);
  --background: oklch(0.16 0.02 280);
  --ring: oklch(0.72 0.15 280);
}

Frequently asked questions

Is Magnetic Button free for commercial use?
Yes. Magnetic Button is MIT licensed, so you can use it in personal and commercial projects without attribution.
Does the magnetic effect hurt performance or accessibility?
No. The pull animates transform only, driven by Motion spring values that write straight to the element, so pointer movement never schedules a React render and never shifts layout. The control is a real anchor or button named by its label, the visible focus ring is identical in both variants and both motion modes, and keyboard focus never moves the control. On touch devices and under reduced motion the effect is disabled entirely and the button behaves as a standard static control with colour hover and focus states.
How do I control how far the button moves?
Use the strength prop. The control translates toward the pointer by the offset from its centre multiplied by strength, which defaults to 0.3, and the displacement is always capped at 16 pixels on each axis whatever value you pass. The label automatically leans an extra 25 percent of the control's offset, so the parallax depth scales with the same prop.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates