Join our Discord Community

React Icon Button

React icon button with particle burst and glow effects on activation. Lucide icons with smooth animations, TypeScript support, and shadcn/ui styling.

Building icon-based interactions?

Join our Discord community for help from other developers.


Icon buttons are everywhere—like buttons, favorite stars, bookmark icons. But most are just static SVGs that change color on click. Boring. No feedback. No delight. Meanwhile, users expect that Instagram-style heart explosion or Twitter's star burst. This React component gives you particle explosions, glow effects, and smooth animations that make every click feel special.

Particle burst on activation

Click to trigger particle explosions and glow effects with smooth spring animations:

Loading component...

Built for React applications with TypeScript and Next.js. Works with any Lucide icon—hearts, stars, bookmarks, thumbs up, you name it. The particle burst uses Framer Motion for physics-based animations that feel natural. RGB color system lets you match any brand. Works seamlessly with shadcn/ui design systems.

Installation

npx shadcn@latest add https://www.shadcn.io/registry/icon-button.json
npx shadcn@latest add https://www.shadcn.io/registry/icon-button.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/icon-button.json
bunx shadcn@latest add https://www.shadcn.io/registry/icon-button.json

Usage

import { IconButton } from "@/components/ui/icon-button";
import { Heart, Star, Bookmark, ThumbsUp } from "lucide-react";

export default function SocialActions() {
  const [liked, setLiked] = useState(false);
  const [starred, setStarred] = useState(false);
  
  return (
    <div className="flex gap-4">
      {/* Heart with red particles */}
      <IconButton
        icon={Heart}
        active={liked}
        color={[239, 68, 68]}  // red-500
        onClick={() => setLiked(!liked)}
        size="md"
      />
      
      {/* Star with golden particles */}
      <IconButton
        icon={Star}
        active={starred}
        color={[251, 191, 36]}  // amber-400
        onClick={() => setStarred(!starred)}
        animate={true}
      />
      
      {/* Bookmark without animations */}
      <IconButton
        icon={Bookmark}
        active={bookmarked}
        color={[59, 130, 246]}  // blue-500
        animate={false}  // No particles, just color change
      />
    </div>
  );
}

Why most icon buttons are lifeless

Developers just toggle a fill color and call it done. Or they add a weak scale animation that nobody notices. The problem? Users are conditioned by social media to expect visual rewards. That heart should explode. That star should burst. These micro-delights trigger dopamine and keep users engaged.

This React component handles the complex animation orchestration: particle physics, glow effects, color transitions, and spring animations. The particles aren't random—they burst outward with physics-based trajectories. The glow pulses with perfect timing. It's the difference between a button that functions and one that delights.

Plus, the RGB color system means you're not locked into preset colors. Match your brand exactly. Create custom themes. Change colors dynamically based on state.

Examples

Different Icons & Colors

Popular icon combinations with matching particle colors:

Loading component...

Size Variants

Four sizes optimized for different UI contexts and touch targets:

Loading component...

Features

  • Particle burst animations with physics-based trajectories and customizable colors
  • Radial glow effects pulsing outward from the icon center on activation
  • Any Lucide icon support with automatic sizing and consistent styling
  • RGB color system for exact brand matching and dynamic theming
  • Four size presets optimized for different UI densities and touch targets
  • Smooth spring animations for natural press and release interactions
  • TypeScript definitions with complete prop types and Lucide icon compatibility
  • Controlled animation toggle allowing static or animated state changes
  • Accessible button semantics with proper ARIA attributes and keyboard support

API Reference

IconButton

The main component for animated icon button interactions.

PropTypeDefaultDescription
iconReact.ElementTyperequiredAny Lucide React icon component
activebooleanfalseCurrent activation state
animatebooleantrueEnable particle and glow animations
size"sm" | "default" | "md" | "lg""default"Button and icon size preset
color[number, number, number][59, 130, 246]RGB color values for theme
transitionTransition{ type: "spring", stiffness: 300, damping: 15 }Spring animation config
onClick() => void-Click handler for state changes
classNamestring-Additional CSS classes
...propsButtonHTMLAttributes-All native button props supported

Size Specifications

Each size is optimized for specific use cases:

SizeButtonIconTouch TargetUse Case
sm24px16px44px paddedInline actions, dense UI
default32px20px44pxStandard interactions
md40px24px48pxMobile-first, touch UI
lg48px28px56pxHero sections, CTAs

Color System

RGB arrays for precise color control:

// Popular color combinations
const colors = {
  red: [239, 68, 68],      // red-500
  pink: [236, 72, 153],    // pink-500
  orange: [249, 115, 22],  // orange-500
  amber: [251, 191, 36],   // amber-400
  yellow: [250, 204, 21],  // yellow-400
  green: [34, 197, 94],    // green-500
  blue: [59, 130, 246],    // blue-500
  purple: [168, 85, 247],  // purple-500
  gray: [107, 114, 128],   // gray-500
};

Common gotchas

Particle performance on mobile: The particle burst creates multiple DOM elements. On low-end devices with many buttons, consider disabling animations (animate={false}) or reducing particle count in the component.

Touch target sizing: Even the sm size maintains a 44px touch target through padding. Don't override this with custom styles—it's there for accessibility.

Color array format: Colors must be RGB arrays, not hex strings or CSS colors. Convert hex to RGB: #ef4444 becomes [239, 68, 68]. There are online converters if needed.

Icon import requirements: Icons must be imported from lucide-react, not inlined SVGs. The component expects Lucide's consistent props interface for proper sizing.

Active state management: The component doesn't manage state internally. You must track active state and update it in the onClick handler. This gives you full control but requires state setup.

Animation cleanup: Rapidly clicking can create multiple particle bursts. The component handles cleanup, but very fast clicking might cause visual overlap. This is intentional for enthusiastic users.

You might also like

Explore other interactive button components for React applications:

Questions developers actually ask