shadcn.io is not affiliated with official shadcn/ui
As the pointer moves over the button, the button leans toward it, following it across its face. When the pointer leaves, it springs back into place with a small overshoot.
Use it for one call to action on a landing page or a hero, where a little motion earns a second look. Don't use it in forms, toolbars or dense layouts, where a moving target is harder to hit; for a quieter answer to the pointer, use the Spotlight Button. It wraps the Button, so variant and size work as usual. Each pointer move writes the offset into two CSS variables that translate the button, and a CSS transition makes the release springy, so nothing re-renders while it moves. It stays still on touch screens, while disabled, and when the system asks for reduced motion.
Installation
Usage
import { MagneticButton } from "@/components/ui/magnetic-button";<MagneticButton>Get started</MagneticButton>Demos
Intensity
intensity is how strongly the button follows the pointer: subtle travels a sixth of the pointer's distance from its center, medium (the default) a third and strong a half. Keep strong for a large button with room around it, since it slides well out of its place.
Accessibility
The movement is visual only: the button is announced and activated as any Button, and focus, Enter and Space work as usual. The pull follows a mouse or a pen, never a touch, and it's off when the system asks for reduced motion, so the button stays where it was laid out.
- Enter
- Activate the button.
- Space
- Activate the button.
FAQ
How does the spring work without an animation library?
While the pointer is over the button, it follows with a short ease-out transition. When the pointer leaves, the offset goes back to zero over half a second with a cubic-bezier that overshoots, which reads as a spring. A data-pulled attribute on the button, set while it follows, switches between the two timings.
The pull feels too floaty. How do I tone it down?
Set intensity="subtle", so the button travels a sixth of the pointer's distance from its center instead of a third.
Does it start moving before the pointer is over it?
No. It follows the pointer only while the pointer is over the button, so it never moves toward a pointer that's just passing by, and it costs nothing while the pointer is elsewhere on the page.
Does the moving button push its neighbors?
No. The pull is a CSS translate, which moves the button without changing the layout, so nothing around it shifts. Leave some room around it so it doesn't slide over its neighbors.
What happens on a touch screen?
Nothing moves. The pull only follows a mouse or a pen, because a finger has no hover and the button would jump under it. A tap presses it as usual.
API Reference
MagneticButton
focusableWhenDisabled?boolean
Whether the button should be focusable when disabled.
- Default
false
intensity?"subtle" | "medium" | "strong"
How strongly the button follows the pointer: subtle travels a sixth
of the pointer's distance from its center, medium a third and
strong a half.
- Type
"subtle" | "medium" | "strong"- Default
"medium"
nativeButton?boolean
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (for example, <div>).
- Default
true
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Merged with the part's classes.
--magnetic-button-xstring
How far the button is pulled across, in pixels.
--magnetic-button-ystring
How far the button is pulled down, in pixels.
Related
- Pro
Spotlight Button
Glow & lightLight that follows the cursor
- Pro
Depth Button
Motion & feedbackA tactile 3D press instead
Ripple Button
Motion & feedbackPress feedback from the click point
Arrow Button
Hover revealsA quieter hover cue for CTAs
- Pro
Flip Button
Hover reveals3D flip reveal on hover
- Pro
Pulse Button
Motion & feedbackDraw the eye without hover