Socket
Book a DemoInstallSign in
Socket

use-attract

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

use-attract

A lightweight React hook for creating magnetic hover effects and interactive pull animations.

1.0.12
latest
Source
npmnpm
Version published
Maintainers
1
Created
Source

use-attract

Magnetic attraction effects for React, made simple.

A lightweight, configurable React hook for creating smooth, interactive "magnetic" UI elements that respond to cursor movement. Transform ordinary components into engaging, interactive experiences with just a few lines of code.

npm version License: MIT React Next.js

🎯 Perfect for: Interactive buttons, floating cards, animated icons, and any UI element that needs that extra touch of magic.

✨ Why use-attract?

  • 🧲 Smooth attraction effects β€” Elements gracefully follow your cursor
  • βš™οΈ Highly configurable β€” Control strength, field radius, and easing
  • πŸ“± Mobile-aware β€” Built-in responsive behavior with useMobile helper
  • πŸ”§ SSR-ready β€” Works seamlessly with Next.js and other SSR frameworks
  • πŸͺΆ Lightweight β€” Zero dependencies, tiny bundle size
  • 🎨 Framework agnostic β€” Works anywhere React hooks work

πŸš€ Quick Demo

'use client';

import { useAttract } from 'use-attract';

function MagneticButton() {
  const { ref, style } = useAttract();

  return (
    <button
      ref={ref}
      style={{
        ...style,
        padding: '12px 24px',
        background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
        color: 'white',
        border: 'none',
        borderRadius: '8px',
        cursor: 'pointer',
      }}
    >
      Hover me! 🧲
    </button>
  );
}

πŸ“¦ Installation

npm install use-attract
yarn add use-attract
pnpm add use-attract

🎯 Usage

Basic Example

'use client'; // Next.js App Router

import { useAttract, useMobile } from 'use-attract';

export default function AttractDemo() {
  const { ref, style } = useAttract({
    strength: 50,      // How strong the magnetic pull is
    magneticField: 32, // Distance in pixels where the effect activates
    lerpFactor: 0.2,   // Smoothness of the animation (0-1)
  });

  const isMobile = useMobile(1280); // Detect mobile screens

  return (
    <div className="demo-container">
      <div
        ref={ref}
        style={{
          ...style,
          width: '120px',
          height: '120px',
          background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
          color: 'white',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          borderRadius: '12px',
          cursor: 'pointer',
          transition: 'box-shadow 0.3s ease',
        }}
        onMouseEnter={(e) => e.target.style.boxShadow = '0 20px 40px rgba(0,0,0,0.2)'}
        onMouseLeave={(e) => e.target.style.boxShadow = 'none'}
      >
        🧲 Magnetic
      </div>
      
      {isMobile !== undefined && (
        <p>Mobile detected: {isMobile ? 'Yes' : 'No'}</p>
      )}
    </div>
  );
}

Advanced Configuration

const { ref, style, position } = useAttract({
  enabled: true,        // Enable/disable the effect
  strength: 75,         // Pull strength (0-100+)
  magneticField: 50,    // Activation radius in pixels
  lerpFactor: 0.15,     // Animation smoothness (lower = smoother)
});

// Access raw position data if needed
console.log(position); // { x: number, y: number }

πŸ“‹ API Reference

useAttract(options)

Creates a magnetic hover effect for an element.

Parameters

OptionTypeDefaultDescription
enabledbooleantrueEnable or disable the magnetic effect
strengthnumber50Strength of the magnetic pull (0-100+)
magneticFieldnumber32Distance in pixels where the effect activates
lerpFactornumber0.2Smoothness of the animation (0-1, lower = smoother)

Returns

PropertyTypeDescription
refRefObjectAttach this to your target element
styleCSSPropertiesSpread this onto your element's style
position{x: number, y: number}Raw transform values (optional)

useMobile(breakpoint)

A responsive helper that detects mobile screens.

Parameters

ParameterTypeDefaultDescription
breakpointnumber768Screen width threshold in pixels

Returns

TypeDescription
boolean | undefinedtrue if screen ≀ breakpoint, undefined during SSR

🎨 Use Cases & Examples

Interactive Buttons

function MagneticCTA() {
  const { ref, style } = useAttract({ strength: 60 });
  
  return (
    <button
      ref={ref}
      style={{
        ...style,
        padding: '16px 32px',
        fontSize: '18px',
        fontWeight: 'bold',
        background: 'linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%)',
        color: 'white',
        border: 'none',
        borderRadius: '50px',
        cursor: 'pointer',
      }}
    >
      Get Started πŸš€
    </button>
  );
}

Product Cards

function ProductCard({ product }) {
  const { ref, style } = useAttract({ 
    strength: 30, 
    magneticField: 40 
  });
  
  return (
    <div
      ref={ref}
      style={{
        ...style,
        width: '300px',
        padding: '20px',
        background: 'white',
        borderRadius: '12px',
        boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
        cursor: 'pointer',
      }}
    >
      <h3>{product.name}</h3>
      <p>${product.price}</p>
    </div>
  );
}

Floating Icons

function FloatingIcon({ icon, label }) {
  const { ref, style } = useAttract({ 
    strength: 25, 
    lerpFactor: 0.1 
  });
  
  return (
    <div
      ref={ref}
      style={{
        ...style,
        width: '80px',
        height: '80px',
        background: 'rgba(255,255,255,0.1)',
        borderRadius: '50%',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: '32px',
        cursor: 'pointer',
        backdropFilter: 'blur(10px)',
      }}
      title={label}
    >
      {icon}
    </div>
  );
}

πŸ”§ Framework Compatibility

FrameworkSupportNotes
Reactβœ… 18.x, 19.x+Full support
Next.jsβœ… 14+Use 'use client' directive
Viteβœ… All versionsWorks out of the box
Create React Appβœ… All versionsWorks out of the box
Remixβœ… All versionsClient-side only
Gatsbyβœ… All versionsClient-side only

🎯 Performance Tips

  • Use enabled: false to disable the effect on mobile devices
  • Adjust lerpFactor for smoother animations (lower values = smoother)
  • Consider using useMobile() to conditionally apply effects
  • The hook automatically cleans up event listeners on unmount
const isMobile = useMobile(768);
const { ref, style } = useAttract({ 
  enabled: !isMobile,  // Disable on mobile
  strength: isMobile ? 0 : 50 
});

🀝 Contributing

We welcome contributions! Here's how you can help:

  • Fork the repository
  • Create a feature branch (git checkout -b feature/amazing-feature)
  • Commit your changes (git commit -m 'Add amazing feature')
  • Push to the branch (git push origin feature/amazing-feature)
  • Open a Pull Request

Development Setup

git clone https://github.com/yourusername/use-attract.git
cd use-attract
npm install
npm run dev

πŸ“„ License

MIT Β© Kevin Davis

🌟 Show Your Support

If this library helped you build something awesome, please consider:

  • ⭐ Star this repository
  • πŸ› Report issues you encounter
  • πŸ’‘ Suggest new features
  • πŸ“’ Share it with your developer friends

Made with ❀️ by developers, for developers.

Transform your React components from ordinary to extraordinary with just a few lines of code.

Keywords

react

FAQs

Package last updated on 04 Jul 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚑️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.