Magnet Button
kokonut-ui/attract-buttonFreeComponent
Attract particles button!
Live preview
live · rendered by the registry
Rendered by kokonut-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://kokonutui.com/r/attract-button.jsonSource
1"use client";23/**4 * @author: @dorianbaffier5 * @description: Attract Button6 * @version: 1.0.07 * @date: 2025-06-268 * @license: MIT9 * @website: https://kokonutui.com10 * @github: https://github.com/kokonut-labs/kokonutui11 */1213import { Magnet } from "lucide-react";14import { motion, useAnimation } from "motion/react";15import { useCallback, useEffect, useState } from "react";16import { Button } from "@/components/ui/button";17import { cn } from "@/lib/utils";1819interface AttractButtonProps20 extends React.ButtonHTMLAttributes<HTMLButtonElement> {21 particleCount?: number;22 attractRadius?: number;23}2425interface Particle {26 id: number;27 x: number;28 y: number;29}3031export default function AttractButton({32 className,33 particleCount = 12,34 attractRadius = 50,35 ...props36}: AttractButtonProps) {37 const [isAttracting, setIsAttracting] = useState(false);38 const [particles, setParticles] = useState<Particle[]>([]);39 const particlesControl = useAnimation();4041 useEffect(() => {42 const newParticles = Array.from({ length: particleCount }, (_, i) => ({43 id: i,44 x: Math.random() * 360 - 180,45 y: Math.random() * 360 - 180,46 }));47 setParticles(newParticles);48 }, [particleCount]);4950 const handleInteractionStart = useCallback(async () => {51 setIsAttracting(true);52 await particlesControl.start({53 x: 0,54 y: 0,55 transition: {56 type: "spring",57 stiffness: 50,58 damping: 10,59 },60 });61 }, [particlesControl]);6263 const handleInteractionEnd = useCallback(async () => {64 setIsAttracting(false);65 await particlesControl.start((i) => ({66 x: particles[i].x,67 y: particles[i].y,68 transition: {69 type: "spring",70 stiffness: 100,71 damping: 15,72 },73 }));74 }, [particlesControl, particles]);7576 return (77 <Button78 className={cn(79 "relative min-w-40 touch-none",80 "bg-violet-100 dark:bg-violet-900",81 "hover:bg-violet-200 dark:hover:bg-violet-800",82 "text-violet-600 dark:text-violet-300",83 "border border-violet-300 dark:border-violet-700",84 "transition-all duration-300",85 className86 )}87 onMouseEnter={handleInteractionStart}88 onMouseLeave={handleInteractionEnd}89 onTouchEnd={handleInteractionEnd}90 onTouchStart={handleInteractionStart}91 {...props}92 >93 {particles.map((_, index) => (94 <motion.div95 animate={particlesControl}96 className={cn(97// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from kokonut-ui
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Search Baraction-search-bar | kokonut-ui | Components | Free | 2 deps · 2 files | |
| AI Input Searchai-input-search | kokonut-ui | Components | Free | 1 dep · 2 files | |
| AI State Loadingai-loading | kokonut-ui | Components | Free | 1 dep | |
| AI Input Selectorai-prompt | kokonut-ui | Components | Free | 2 deps · 4 files | |
| AI Text Loadingai-text-loading | kokonut-ui | Components | Free | 1 dep | |
| AI Voiceai-voice | kokonut-ui | Components | Free | 2 deps | |
| Apple Activity Cardapple-activity-card | kokonut-ui | Components | Free | 1 dep | |
| Avatar Pickeravatar-picker | kokonut-ui | Components | Free | 2 deps |
