Magnetic Button
A button that leans toward the pointer as it approaches.
- buttons
- magnetic
- button
- pointer
- proximity
- cta
move your pointer nearby
Quick usage
import { MagneticButton } from "@pinky-ui/components";
<MagneticButton variant="primary" strength={0.4}>
Explore components
</MagneticButton>Presets
Default
Balanced pull for primary actions.
strength={0.4} range={110} maxOffset={8}
Whisper
Noticeable only once you are close.
strength={0.25} range={70} maxOffset={5}
Wide field
Reacts from far away — good for isolated hero buttons.
strength={0.35} range={180} maxOffset={10}
Install
Add @pinky-ui/components as a dependency, or use the CLI to copy this component's source directly into your project — no dependency to manage, fully editable.
npm install @pinky-ui/componentspnpm add @pinky-ui/componentsyarn add @pinky-ui/componentsnpx pinky-ui add magnetic-buttonPrefer to run the whole repository locally instead?
git clone https://github.com/florash/Pinky-UI.git
cd Pinky-UI
npm install
npm run devProps
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "primary" | "soft" | "ghost" | "primary" | Visual weight of the button. |
| size | "sm" | "md" | "lg" | "md" | Control height and padding. |
| strength | number | 0.4 | Fraction of the pointer offset that is followed. |
| range | number | 110 | Proximity field around the button, in px. |
| maxOffset | number | 8 | Hard cap on travel, in px. |
| wrapperClassName | string | — | Layout classes for the magnetic wrapper. `className` styles the button itself. |
Accessibility
- Renders a real <button>; every native attribute and event is forwarded.
- Ref forwarding is supported for focus management.
- The magnetic wrapper never moves the button's hit area away from its label.
- Keyboard focus shows the global focus ring; the effect requires no pointer.
- Disabled buttons opt out of magnetism as well as clicks.
Reduced motion
With prefers-reduced-motion: reduce, the button does not move at all. Hover and focus styling still change, so the affordance is unchanged.
When to use
- Primary calls to action with space around them
- Hero and landing-page actions
- Sparse toolbars where a little life is welcome
When not to use
- Dense button groups, where overlapping fields fight each other
- Destructive actions that should feel deliberate
- Inside tables or list rows
Playground
Mira Odaka
Interaction designer
Drag your pointer across this card and watch how the parameters change its character.
<JellyCard
elasticity={0.35}
intensity={0.18}
hoverScale={1.02}
radius="xl"
>
<ProfileCard />
</JellyCard>