Free & open source, built for every frontend stack. Star Exhuma on GitHub
ExhumaBeta
DocsComponentsBlog

Getting Started

  • Introduction
  • Installation
  • Theming & Dark Mode
  • CLI Reference

Architecture

  • Kinetic Methodology
  • Ecosystem Contracts
  • Lifecycle & Memory Safety

Components

  • All Components20
Cards8
  • Stacking Cards
  • Horizontal Scroller
  • Tilt Card
  • Spotlight Card
  • Border Beam
  • Card Swipe Stack
  • Comparison Slider
  • Expandable Card
Layouts6
  • CSS Masonry
  • Row Masonry
  • Auto Grid
  • Infinite Marquee
  • Bento Grid
  • Diamond Grid
Navigation2
  • Morphing Tabs
  • Floating Dock
Primitives4
  • Accordion
  • Number Ticker
  • Magnetic Button
  • Cursor Tooltip
// DOCS·Components·Primitives

Magnetic Button

Inverted spring pull field button that magnetically attracts cursor proximity with critically damped release snaps.

Target Environment
+
+
CLI Installation
React
$pnpm dlxexhumaaddmagnetic-button--flavor=react
// 01·Workbench

Interactive Specification & Studio

primitives
Preset:
Viewport
Fluid 100%
MAGNETIC GAUSSIAN FIELD120 FPS COMPOSITOR

Move cursor inside the field rings to engage the physics attractor with invariant reference frame coordinates.

R: 120px•K: 0.35•Clamp: ±36px
Spring: λ=18
Parameters
7 Props
// 02·Usage

Quick Start & Consumer Example

Copy-paste ready implementation for React (.tsx). Automatically updates when you modify parameters in the Workbench above.

+
+
MagneticButtonDemo.tsx
React (.tsx)
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;
// 03·API Contract

Props & Configuration

Exhaustive parameter contract for Magnetic Button. Validated in the live Studio workbench above and statically checked across all 13 ecosystem templates.

PropTypeDefaultDescription
strength
number0.35Displacement factor relative to cursor distance.
radius
number120Influence radius threshold in pixels.
springDamping
number18Exponential decay rate for critically damped snaps.
maxDisplacement
number36Maximum absolute cursor attraction displacement cap in pixels.
text
stringMagnetic AttractionInner label text for the button.
dualTier
booleanfalseDual-layer displacement split between housing and content.
shockwave
booleanfalseRadial expanding ring on click.
strength
number

Displacement factor relative to cursor distance.

Default:0.35
radius
number

Influence radius threshold in pixels.

Default:120
springDamping
number

Exponential decay rate for critically damped snaps.

Default:18
maxDisplacement
number

Maximum absolute cursor attraction displacement cap in pixels.

Default:36
text
string

Inner label text for the button.

Default:Magnetic Attraction
dualTier
boolean

Dual-layer displacement split between housing and content.

Default:false
shockwave
boolean

Radial expanding ring on click.

Default:false
// 04·Source Code

Component Source

Component source definition for React (.tsx). Toggle between the clean wrapper and the standalone ejected engine micro-kernel.

+
+
MagneticButton.tsx
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;
// 05·Architecture

Lifecycle Safety & Performance

Engineered for high-frequency user interactions with zero memory leaks.

Teardown

Deterministic Cleanup

All pointer event listeners, scroll handlers, and resize observers are cleanly destroyed on component unmount, preventing lingering background processes.
Compositor

GPU Compositor Acceleration

Transform and opacity modifications run directly on the GPU compositor thread using will-change: transform without triggering browser layout recalculations.
// 06·a11y

Accessibility Considerations

Fully compliant with WCAG guidelines and respects user motion preferences.

Motion

prefers-reduced-motion Support

When a user has prefers-reduced-motion: reduce enabled in their operating system, Exhuma components automatically disable 3D gyroscope tilt and spring animations, rendering static accessible content.
Number TickerCursor Tooltip