Customize
Usage
import { MagneticButton } from "@/components/motionkit/magnetic-button";
<MagneticButton>
Get started
</MagneticButton>Motion
The exact curves this component runs, plotted with Motion's own maths.
Follow
Pointer moves over the button
Works in the App Router as is. Requires Tailwind CSS v4.
npm install motionSave as components/motionkit/magnetic-button.tsx.
"use client";
import { useRef, type ComponentProps, type PointerEvent } from "react";
import { motion, useMotionValue, useReducedMotion, useSpring } from "motion/react";
type MagneticButtonProps = Omit<ComponentProps<typeof motion.button>, "ref"> & {
/** How far (0–1) the button follows the pointer. */
strength?: number;
};
export function MagneticButton({
strength = 0.35,
className = "",
children,
onPointerMove,
onPointerLeave,
...props
}: MagneticButtonProps) {
const ref = useRef<HTMLButtonElement>(null);
const reduceMotion = useReducedMotion();
const x = useSpring(useMotionValue(0), { stiffness: 220, damping: 16, mass: 0.4 });
const y = useSpring(useMotionValue(0), { stiffness: 220, damping: 16, mass: 0.4 });
function handleMove(event: PointerEvent<HTMLButtonElement>) {
onPointerMove?.(event);
if (reduceMotion || !ref.current) return;
const rect = ref.current.getBoundingClientRect();
x.set((event.clientX - rect.left - rect.width / 2) * strength);
y.set((event.clientY - rect.top - rect.height / 2) * strength);
}
function handleLeave(event: PointerEvent<HTMLButtonElement>) {
onPointerLeave?.(event);
x.set(0);
y.set(0);
}
return (
<motion.button
ref={ref}
style={{ x, y }}
whileTap={{ scale: 0.96 }}
onPointerMove={handleMove}
onPointerLeave={handleLeave}
className={`relative inline-flex items-center justify-center gap-2 rounded-xl bg-[#0E7C86] px-5 py-3 text-sm font-medium text-white shadow-[0_8px_30px_-8px_rgb(14_124_134/0.6)] transition-colors hover:bg-[#2E9098] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#5FAEB4] ${className}`}
{...props}
>
{children}
</motion.button>
);
}
| Prop | Type | Default | Description |
|---|---|---|---|
| strength | number | 0.35 | How far (0–1) the button follows the pointer. |
| ...props | motion.button props | — | Any button or Motion prop, e.g. onClick. |
Pull me
Magnetic Letters
Each letter leans toward the cursor and springs home, like a magnetic button for every character.
Shimmer Button
A dark button with a light sweep that draws the eye without shouting.
Hold to Confirm
A button that fills while held, so destructive actions can never happen by accident.