MOVE INSIDE
INTERACTION_012CSS + JS
Custom Cursor
Dot plus trailing ring with contextual labels.
Mouse / MediumView
The button tracks the cursor within a proximity radius, translating a fraction of the pointer offset and snapping home on exit. The single most stolen interaction on the internet.
const btn = document.querySelector(".magnetic");
const STRENGTH = 0.35;
let frame;
btn.addEventListener("pointermove", (e) => {
cancelAnimationFrame(frame);
frame = requestAnimationFrame(() => {
const r = btn.getBoundingClientRect();
const x = e.clientX - (r.left + r.width / 2);
const y = e.clientY - (r.top + r.height / 2);
btn.style.transform = `translate(${x * STRENGTH}px, ${y * STRENGTH}px)`;
});
});
btn.addEventListener("pointerleave", () => {
btn.style.transform = "translate(0, 0)";
});export function MagneticButton({ children }: { children: React.ReactNode }) {
const ref = useRef<HTMLButtonElement>(null);
const onMove = (e: React.PointerEvent) => {
const el = ref.current;
if (!el || !window.matchMedia("(pointer: fine)").matches) return;
const r = el.getBoundingClientRect();
const x = (e.clientX - (r.left + r.width / 2)) * 0.35;
const y = (e.clientY - (r.top + r.height / 2)) * 0.35;
el.style.transform = `translate(${x}px, ${y}px)`;
};
return (
<button
ref={ref}
onPointerMove={onMove}
onPointerLeave={() => ref.current && (ref.current.style.transform = "")}
className="rounded-full bg-white px-7 py-3.5 text-black transition-transform duration-500 ease-[cubic-bezier(0.22,1,0.36,1)]"
>
{children}
</button>
);
}Dot plus trailing ring with contextual labels.
Weightless 2px rise with an edge highlight on hover.
A diagonal chrome glint travels across the surface on hover.