Magnetic Button
A restrained interaction experiment exploring attraction, release, and the feeling of weight in a small interface object.
- Difficulty
- Beginner
- Build time
- 60–90 minutes
- Published
- Jul 27, 2026
- Updated
- Jul 27, 2026
Interactive preview shell
PreviewMove toward the button and feel the attraction.
01 / Overview
A small button with a sense of weight.
Magnetic Button uses pointer distance to pull a CTA toward the user without making the interaction feel noisy or difficult to control.
02 / What you will learn
The idea behind the interaction.
- Read pointer position relative to a button’s bounds.
- Translate a normalized offset into a restrained movement range.
- Reset the interaction cleanly when the pointer leaves.
03 / How it works
Structure first. Tuning second.
The button owns its offset. Pointer coordinates are normalized to the center of the element, scaled to a small range, and reset on leave.
04 / Build sequence
Step by step
Measure the button
Normalize the pull
Release with intent
import { useState } from "react";
export function MagneticButton() {
const [offset, setOffset] = useState({ x: 0, y: 0 });
function trackPointer(event: React.PointerEvent<HTMLButtonElement>) {
const bounds = event.currentTarget.getBoundingClientRect();
setOffset({
x: ((event.clientX - bounds.left) / bounds.width - 0.5) * 24,
y: ((event.clientY - bounds.top) / bounds.height - 0.5) * 24,
});
}
return (
<button
onPointerMove={trackPointer}
onPointerLeave={() => setOffset({ x: 0, y: 0 })}
style={{ transform: `translate3d(${offset.x}px, ${offset.y}px, 0)` }}
>
Start a conversation
</button>
);
}05 / Notes
Production details belong in the experiment.
06 / Props & API
A stable surface for the future build.
- reducedMotion
- boolean
- Keeps the preview readable without nonessential movement.
- className
- string
- Allows the experiment shell to inherit the MADLAB layout.
- status
- MadlabStatus
- Communicates whether the experiment is draft, preview, or published.
07 / Performance
Measure before adding complexity.
Keep animation work local to the interaction, avoid unnecessary state updates, and pause nonessential work when the preview is not visible.
08 / Accessibility
The visual idea still needs a clear interface.
Every future experiment should have a semantic name, keyboard path, reduced-motion fallback, usable contrast, and a text explanation that does not depend on the animation.
09 / Mobile
A considered small screen composition.
On narrow screens, the preview should simplify its visual workload, preserve the primary idea, and never require horizontal scrolling to understand the experiment.
Source actions
Final source actions
Source is available in the implementation block above.
Continue exploring