Magnetic Button
Inverted spring pull field button that magnetically attracts cursor proximity with critically damped release snaps.
Interactive Specification & Studio
Move cursor inside the field rings to engage the physics attractor with invariant reference frame coordinates.
Quick Start & Consumer Example
Copy-paste ready implementation for React (.tsx). Automatically updates when you modify parameters in the Workbench above.
import * as React from 'react';
import { MagneticButton } from './MagneticButton';
import { Sparkles, ArrowRight } from 'lucide-react';
export function MagneticButtonDemo() {
return (
<section className="relative flex flex-col items-center justify-center overflow-hidden rounded-3xl border border-border/80 bg-card/60 p-8 sm:p-12 text-center shadow-2xl backdrop-blur-xl">
<div className="inline-flex items-center gap-2 rounded-full border border-foreground/20 bg-foreground/5 px-4 py-1.5 text-xs font-mono font-semibold text-foreground">
<Sparkles className="size-3.5" />
<span>GAUSSIAN PROXIMITY ATTRACTOR</span>
</div>
<h2 className="mt-6 text-3xl font-black tracking-tight text-foreground sm:text-5xl">
Physics you can feel.
</h2>
<p className="mt-4 max-w-lg text-sm leading-relaxed text-muted-foreground sm:text-base">
Inverted spring pull field dynamically draws the cursor toward high-priority conversion targets with 120 FPS sub-pixel accuracy.
</p>
{/* Visual Magnetic Attractor Field */}
<div className="relative my-8 flex h-60 w-full items-center justify-center overflow-hidden sm:h-68">
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div
style={{ width: '240px', height: '240px' }}
className="border-foreground/15 absolute rounded-full border border-dashed animate-[spin_60s_linear_infinite]"
/>
<div
style={{ width: '180px', height: '180px' }}
className="border-foreground/15 absolute rounded-full border border-dotted"
/>
<div
style={{ width: '120px', height: '120px' }}
className="border-foreground/10 absolute rounded-full border"
/>
</div>
<div className="bg-foreground/5 pointer-events-none absolute -inset-6 rounded-full blur-2xl" />
<MagneticButton
strength={0.35}
radius={120}
springDamping={18}
maxDisplacement={36}
className="group relative z-10 cursor-pointer rounded-2xl bg-foreground px-8 py-4 text-xs sm:text-sm font-black text-background shadow-2xl transition-transform hover:scale-105 active:scale-95 will-change-transform select-none"
>
<span className="flex items-center gap-2.5">
<Sparkles className="size-4 transition-transform group-hover:scale-110 group-hover:rotate-12" />
<span>Magnetic Attraction</span>
<ArrowRight className="size-4 transition-transform group-hover:translate-x-1" />
</span>
</MagneticButton>
</div>
</section>
);
}
export default MagneticButtonDemo;
Props & Configuration
Exhaustive parameter contract for Magnetic Button. Validated in the live Studio workbench above and statically checked across all 13 ecosystem templates.
| Prop | Type | Default | Description |
|---|---|---|---|
strength | number | 0.35 | Displacement factor relative to cursor distance. |
radius | number | 120 | Influence radius threshold in pixels. |
springDamping | number | 18 | Exponential decay rate for critically damped snaps. |
maxDisplacement | number | 36 | Maximum absolute cursor attraction displacement cap in pixels. |
text | string | Magnetic Attraction | Inner label text for the button. |
dualTier | boolean | false | Dual-layer displacement split between housing and content. |
shockwave | boolean | false | Radial expanding ring on click. |
Displacement factor relative to cursor distance.
Influence radius threshold in pixels.
Exponential decay rate for critically damped snaps.
Maximum absolute cursor attraction displacement cap in pixels.
Inner label text for the button.
Dual-layer displacement split between housing and content.
Radial expanding ring on click.
Component Source
Component source definition for React (.tsx). Toggle between the clean wrapper and the standalone ejected engine micro-kernel.
import * as React from 'react';
import {
MagneticButton as CoreMagneticButton,
type MagneticButtonProps as CoreMagneticButtonProps,
} from '@exhuma/core';
import { clsx } from 'clsx';
export interface MagneticButtonProps extends CoreMagneticButtonProps {
className?: string;
}
export const MagneticButton = React.forwardRef<HTMLButtonElement, MagneticButtonProps>(
(
{
children,
strength = 0.35,
radius = 120,
springDamping = 18,
maxDisplacement = 36,
className,
...props
},
ref
) => {
return (
<CoreMagneticButton
ref={ref}
strength={strength}
radius={radius}
springDamping={springDamping}
maxDisplacement={maxDisplacement}
className={clsx(
'group relative inline-flex items-center justify-center gap-2.5 rounded-2xl bg-foreground px-8 py-4 text-sm font-black text-background shadow-2xl transition-transform hover:scale-105 active:scale-95 cursor-pointer will-change-transform select-none',
className
)}
{...props}
>
{children ?? 'Magnetic Attraction'}
</CoreMagneticButton>
);
}
);
MagneticButton.displayName = 'MagneticButton';
export default MagneticButton;
Lifecycle Safety & Performance
Engineered for high-frequency user interactions with zero memory leaks.
Deterministic Cleanup
GPU Compositor Acceleration
will-change: transform without triggering browser layout recalculations.Accessibility Considerations
Fully compliant with WCAG guidelines and respects user motion preferences.
prefers-reduced-motion Support
prefers-reduced-motion: reduce enabled in their operating system, Exhuma components automatically disable 3D gyroscope tilt and spring animations, rendering static accessible content.