Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/www/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,12 @@ export const docsConfig: DocsConfig = {
items: [],
label: "",
},
{
title: "Magnetic Button",
href: "/docs/components/magnetic-button",
items: [],
label: "New",
},
],
},
{
Expand Down
73 changes: 73 additions & 0 deletions apps/www/content/docs/components/magnetic-button.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: Magnetic Button
date: 2026-07-08
description: A button with a smooth magnetic hover effect that follows the cursor.
author: Tonoy
published: true
---

<ComponentPreview name="magnetic-button-demo" />

## Installation

<Tabs defaultValue="cli">

<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>

<TabsContent value="cli">

```bash
npx shadcn@latest add @magicui/magnetic-button
```

</TabsContent>

<TabsContent value="manual">

<Steps>

<Step>Copy and paste the following code into your project.</Step>

<ComponentSource name="magnetic-button" />

<Step>Update the import paths to match your project setup.</Step>

<Step>Install Motion if it isn't already installed.</Step>

```bash
npm install motion
```

</Steps>

</TabsContent>

</Tabs>

## Usage

```tsx showLineNumbers
import { MagneticButton } from "@/components/ui/magnetic-button"
```

```tsx showLineNumbers
<MagneticButton>Hover Me</MagneticButton>
```

## Props

| Prop | Type | Default | Description |
| ------------------ | ----------------------------------------------- | -------------------------------------------- | ----------------------------------------------------- |
| `children` | `React.ReactNode` | `-` | The content displayed inside the button. |
| `className` | `string` | `-` | Additional class names applied to the button. |
| `magnetic` | `boolean` | `true` | Enables or disables the magnetic hover effect. |
| `magneticStrength` | `number` | `0.2` | Controls how far the content moves toward the cursor. |
| `spring` | `SpringOptions` | `{ stiffness: 180, damping: 18, mass: 0.2 }` | Spring configuration for the magnetic animation. |
| `...props` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | `-` | All native button attributes are supported. |

## Credits

- Credit to [@Tonoy](https://github.com/Tonoy3951573)
116 changes: 116 additions & 0 deletions apps/www/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12269,6 +12269,122 @@ export default function MagicCardDemo() {



===== COMPONENT: magnetic-button =====
Title: Magnetic Button
Description: A button with a smooth magnetic hover interaction powered by Motion.

--- file: magicui/magnetic-button.tsx ---
"use client"

import * as React from "react"
import {
motion,
useMotionValue,
useSpring,
type SpringOptions,
} from "motion/react"

import { cn } from "@/lib/utils"

interface MagneticButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
magnetic?: boolean
magneticStrength?: number
spring?: SpringOptions
}

export function MagneticButton({
children,
className,
magnetic = true,
magneticStrength = 0.2,
spring,
onMouseMove,
onMouseLeave,
...props
}: MagneticButtonProps) {
const buttonRef = React.useRef<HTMLButtonElement>(null)

const x = useMotionValue(0)
const y = useMotionValue(0)

const springX = useSpring(x, {
stiffness: 180,
damping: 18,
mass: 0.2,
...spring,
})

const springY = useSpring(y, {
stiffness: 180,
damping: 18,
mass: 0.2,
...spring,
})

const handleMouseMove = (e: React.MouseEvent<HTMLButtonElement>) => {
onMouseMove?.(e)

if (!magnetic || !buttonRef.current) return

const rect = buttonRef.current.getBoundingClientRect()

const dx = (e.clientX - (rect.left + rect.width / 2)) * magneticStrength

const dy = (e.clientY - (rect.top + rect.height / 2)) * magneticStrength

x.set(dx)
y.set(dy)
}

const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {
onMouseLeave?.(e)

x.set(0)
y.set(0)
}

return (
<button
ref={buttonRef}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
className={cn(
"relative inline-flex items-center justify-center overflow-hidden rounded-full",
"border-border bg-background text-foreground border",
"px-6 py-3 text-sm font-medium shadow-sm",
"hover:bg-accent hover:text-accent-foreground transition-colors",
"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none",
"disabled:pointer-events-none disabled:opacity-50",
className
)}
{...props}
>
<motion.span
style={{
x: springX,
y: springY,
}}
className="flex items-center gap-2"
>
{children}
</motion.span>
</button>
)
}


===== EXAMPLE: magnetic-button-demo =====
Title: magnetic-button-demo

--- file: example/magnetic-button-demo.tsx ---
import { MagneticButton } from "../magicui/magnetic-button"

export default function MagneticButtonDemo() {
return <MagneticButton>Hover me</MagneticButton>
}



===== COMPONENT: marquee =====
Title: Marquee
Description: An infinite scrolling component that can be used to display text, images, or videos.
Expand Down
2 changes: 2 additions & 0 deletions apps/www/public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ This file provides LLM-friendly entry points to documentation and examples.
- [Light Rays](https://magicui.design/docs/components/light-rays): A component with animated light rays which shine down from above.
- [Line Shadow Text](https://magicui.design/docs/components/line-shadow-text): A text component with a moving line shadow.
- [Magic Card](https://magicui.design/docs/components/magic-card): A spotlight effect that follows your mouse cursor and highlights borders on hover.
- [Magnetic Button](https://magicui.design/docs/components/magnetic-button): A button with a smooth magnetic hover interaction powered by Motion.
- [Marquee](https://magicui.design/docs/components/marquee): An infinite scrolling component that can be used to display text, images, or videos.
- [Meteors](https://magicui.design/docs/components/meteors): A meteor shower effect.
- [Morphing Text](https://magicui.design/docs/components/morphing-text): A dynamic text morphing component for Magic UI.
Expand Down Expand Up @@ -138,6 +139,7 @@ This file provides LLM-friendly entry points to documentation and examples.
- [Tweet Card Demo](https://github.com/magicuidesign/magicui/blob/main/example/tweet-card-demo.tsx): Example usage
- [Tweet Card Images](https://github.com/magicuidesign/magicui/blob/main/example/tweet-card-images.tsx): Example usage
- [Tweet Card Meta Preview](https://github.com/magicuidesign/magicui/blob/main/example/tweet-card-meta-preview.tsx): Example usage
- [magnetic-button-demo](https://github.com/magicuidesign/magicui/blob/main/example/magnetic-button-demo.tsx): Example usage
- [Shimmer Button Demo](https://github.com/magicuidesign/magicui/blob/main/example/shimmer-button-demo.tsx): Example usage
- [Bento Demo](https://github.com/magicuidesign/magicui/blob/main/example/bento-demo.tsx): Example usage
- [Bento Vertical Demo](https://github.com/magicuidesign/magicui/blob/main/example/bento-demo-vertical.tsx): Example usage
Expand Down
16 changes: 16 additions & 0 deletions apps/www/public/r/magnetic-button-demo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "magnetic-button-demo",
"type": "registry:example",
"description": "A demo of the magnetic button.",
"registryDependencies": [
"@magicui/magnetic-button"
],
"files": [
{
"path": "registry/example/magnetic-button-demo.tsx",
"content": "import { MagneticButton } from \"../magicui/magnetic-button\"\n\nexport default function MagneticButtonDemo() {\n return <MagneticButton>Hover me</MagneticButton>\n}\n",
"type": "registry:example"
}
]
}
17 changes: 17 additions & 0 deletions apps/www/public/r/magnetic-button.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "magnetic-button",
"type": "registry:ui",
"title": "Magnetic Button",
"description": "A button with a smooth magnetic hover interaction powered by Motion.",
"dependencies": [
"motion"
],
"files": [
{
"path": "registry/magicui/magnetic-button.tsx",
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport {\n motion,\n useMotionValue,\n useSpring,\n type SpringOptions,\n} from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\ninterface MagneticButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n magnetic?: boolean\n magneticStrength?: number\n spring?: SpringOptions\n}\n\nexport function MagneticButton({\n children,\n className,\n magnetic = true,\n magneticStrength = 0.2,\n spring,\n onMouseMove,\n onMouseLeave,\n ...props\n}: MagneticButtonProps) {\n const buttonRef = React.useRef<HTMLButtonElement>(null)\n\n const x = useMotionValue(0)\n const y = useMotionValue(0)\n\n const springX = useSpring(x, {\n stiffness: 180,\n damping: 18,\n mass: 0.2,\n ...spring,\n })\n\n const springY = useSpring(y, {\n stiffness: 180,\n damping: 18,\n mass: 0.2,\n ...spring,\n })\n\n const handleMouseMove = (e: React.MouseEvent<HTMLButtonElement>) => {\n onMouseMove?.(e)\n\n if (!magnetic || !buttonRef.current) return\n\n const rect = buttonRef.current.getBoundingClientRect()\n\n const dx = (e.clientX - (rect.left + rect.width / 2)) * magneticStrength\n\n const dy = (e.clientY - (rect.top + rect.height / 2)) * magneticStrength\n\n x.set(dx)\n y.set(dy)\n }\n\n const handleMouseLeave = (e: React.MouseEvent<HTMLButtonElement>) => {\n onMouseLeave?.(e)\n\n x.set(0)\n y.set(0)\n }\n\n return (\n <button\n ref={buttonRef}\n onMouseMove={handleMouseMove}\n onMouseLeave={handleMouseLeave}\n className={cn(\n \"relative inline-flex items-center justify-center overflow-hidden rounded-full\",\n \"border-border bg-background text-foreground border\",\n \"px-6 py-3 text-sm font-medium shadow-sm\",\n \"hover:bg-accent hover:text-accent-foreground transition-colors\",\n \"focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <motion.span\n style={{\n x: springX,\n y: springY,\n }}\n className=\"flex items-center gap-2\"\n >\n {children}\n </motion.span>\n </button>\n )\n}\n",
"type": "registry:ui"
}
]
}
29 changes: 29 additions & 0 deletions apps/www/public/r/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,21 @@
}
]
},
{
"name": "magnetic-button",
"type": "registry:ui",
"title": "Magnetic Button",
"description": "A button with a smooth magnetic hover interaction powered by Motion.",
"dependencies": [
"motion"
],
"files": [
{
"path": "registry/magicui/magnetic-button.tsx",
"type": "registry:ui"
}
]
},
{
"name": "shimmer-button",
"type": "registry:ui",
Expand Down Expand Up @@ -2162,6 +2177,20 @@
}
]
},
{
"name": "magnetic-button-demo",
"type": "registry:example",
"description": "A demo of the magnetic button.",
"registryDependencies": [
"@magicui/magnetic-button"
],
"files": [
{
"path": "registry/example/magnetic-button-demo.tsx",
"type": "registry:example"
}
]
},
{
"name": "shimmer-button-demo",
"type": "registry:example",
Expand Down
29 changes: 29 additions & 0 deletions apps/www/public/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,21 @@
}
]
},
{
"name": "magnetic-button",
"type": "registry:ui",
"title": "Magnetic Button",
"description": "A button with a smooth magnetic hover interaction powered by Motion.",
"dependencies": [
"motion"
],
"files": [
{
"path": "registry/magicui/magnetic-button.tsx",
"type": "registry:ui"
}
]
},
{
"name": "shimmer-button",
"type": "registry:ui",
Expand Down Expand Up @@ -2162,6 +2177,20 @@
}
]
},
{
"name": "magnetic-button-demo",
"type": "registry:example",
"description": "A demo of the magnetic button.",
"registryDependencies": [
"@magicui/magnetic-button"
],
"files": [
{
"path": "registry/example/magnetic-button-demo.tsx",
"type": "registry:example"
}
]
},
{
"name": "shimmer-button-demo",
"type": "registry:example",
Expand Down
29 changes: 29 additions & 0 deletions apps/www/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,21 @@
}
]
},
{
"name": "magnetic-button",
"type": "registry:ui",
"title": "Magnetic Button",
"description": "A button with a smooth magnetic hover interaction powered by Motion.",
"dependencies": [
"motion"
],
"files": [
{
"path": "registry/magicui/magnetic-button.tsx",
"type": "registry:ui"
}
]
},
{
"name": "shimmer-button",
"type": "registry:ui",
Expand Down Expand Up @@ -2162,6 +2177,20 @@
}
]
},
{
"name": "magnetic-button-demo",
"type": "registry:example",
"description": "A demo of the magnetic button.",
"registryDependencies": [
"@magicui/magnetic-button"
],
"files": [
{
"path": "registry/example/magnetic-button-demo.tsx",
"type": "registry:example"
}
]
},
{
"name": "shimmer-button-demo",
"type": "registry:example",
Expand Down
Loading
Loading