npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fmarlats/react-like-button

v1.1.4

Published

Animated React like button component with configurable multi clicks to fill the button, particle animations on click, all customizable. Supports Tailwind CSS and vanilla CSS. TypeScript-ready and accessible.

Readme

React Like Button

npm version bundle size TypeScript License: MIT

| Custom heart with on complete state | Classic button | Like shaped cursor | Gold stars particle | |--------|--------|--------|--------| | Full heart SVG | Round with sparks | Square with emeralds | Square with stars |

| Dislike button round | Dislike button square | |--------|--------| | Dislike button round | Dislike button square |

(You can make any kind of reaction buttons really)

(The gifs are accelerated and chopped, the effects would render better in real life)

Test it yourself: StackBlitz Playground

An animated React like button component with configurable multi clicks to fill the button, particle animations on click, all customizable. Supports Tailwind CSS and vanilla CSS. TypeScript-ready and accessible.

Features

  • 🎯 Multi like Fill Animation - You can click and like multiple times until full (configurable)
  • Particle Effects - 5 built-in presets + full customization when you click
  • 🎭 Custom Shapes - Circle, rounded, or custom
  • 🖱️ Custom Cursors - Built-in presets (heart, star, thumbs-up) or custom
  • 🎨 Fully Customizable - Colors, sizes, styles, and more
  • 📦 Two Versions - Tailwind CSS or vanilla CSS
  • Accessible - ARIA labels and keyboard support
  • 📱 Responsive - Works on all screen sizes
  • 🔒 TypeScript - Full type safety

Installation

npm install @fmarlats/react-like-button
# or
yarn add @fmarlats/react-like-button
# or
pnpm add @fmarlats/react-like-button

Quick Start

Tailwind CSS Version

import { LikeButton } from '@fmarlats/react-like-button';
import '@fmarlats/react-like-button/like-button.css'; // Required for animations

function App() {
  return (
    <LikeButton
      onClick={(clicks) => console.log('Total clicks:', clicks)}
      particlePreset="burst"
    />
  );
}

Vanilla CSS Version

import { LikeButtonVanilla } from '@fmarlats/react-like-button';
import '@fmarlats/react-like-button/styles.css';

function App() {
  return (
    <LikeButtonVanilla
      onClick={(clicks) => console.log('Total clicks:', clicks)}
      particlePreset="confetti"
    />
  );
}

Particle Effects

Disable Particles

// Disable particle effects entirely
<LikeButton showParticles={false} />

Disable Wave Animation

// Disable wave animation (flat fill color)
<LikeButton showWaves={false} />

// Disable both waves and particles for a minimal look
<LikeButton showWaves={false} showParticles={false} />

Built-in Presets

Choose from 5 designed particle effects:

// Quick explosion of hearts (12 particles)
<LikeButton particlePreset="burst" />

// Upward spray effect (10 particles)
<LikeButton particlePreset="fountain" />

// Colorful celebration (15 particles)
<LikeButton particlePreset="confetti" />

// Subtle floating effect (6 particles)
<LikeButton particlePreset="gentle" />

// Explosive sparkles (16 particles)
<LikeButton particlePreset="fireworks" />

Custom Particle Configuration

Or fully customize particle behavior:

<LikeButton particleConfig={{
  shape: 'star',                        // 'heart' | 'star' | 'circle' | 'square' | 'sparkle'
  colors: ['#FFD700', '#FFA500'],       // Array of colors
  count: 15,                            // Number of particles
  speed: 600,                           // Animation duration (ms)
  distance: { min: 80, max: 120 },      // Travel distance (px)
  spread: 180,                          // Spread angle (degrees)
  spreadOffset: -90,                    // Starting angle (0=right, 90=down, 180=left, 270=up)
  size: { min: 1.2, max: 2.0 },         // Size range (scale multiplier)
  easing: 'cubic-bezier(0.22, 1, 0.36, 1)',  // CSS easing function
  fadeOut: true                         // Fade out during animation
}} />

Combine Preset with Custom Config

Start with a preset and override specific properties:

<LikeButton 
  particlePreset="burst" 
  particleConfig={{ 
    count: 20,
    colors: ['#ff0000', '#00ff00', '#0000ff']
  }} 
/>

Basic Usage

Click Tracking

<LikeButton
  maxClicks={10}
  onClick={(clicks) => console.log('Clicks:', clicks)}
  onRightClick={(clicks) => console.log('Right click at:', clicks)}
/>

Uncontrolled with Initial Value

// Start with 3 clicks already filled
<LikeButton defaultClicks={3} maxClicks={10} />

Controlled Mode

const [clicks, setClicks] = useState(0);

// Using onChange (simpler, ideal for state setters)
<LikeButton
  clicks={clicks}
  onChange={setClicks}
  maxClicks={5}
/>

// Using onClick (when you need the event)
<LikeButton
  clicks={clicks}
  onClick={(newClicks, event) => {
    setClicks(newClicks);
    event.stopPropagation();
  }}
  maxClicks={5}
/>

Custom Colors

<LikeButton 
  fillColor="#ff0000"
  waveColor="#ff6666"
  size={120}
/>

Custom Shapes

// Built-in shapes
<LikeButton shape="circle" />
<LikeButton shape="rounded" />

// Custom clip-path
<LikeButton shape={{ 
  clipPath: "polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)" 
}} />

Custom Cursors

// Built-in cursor presets
<LikeButton cursor="heart" />
<LikeButton cursor="star" />
<LikeButton cursor="thumbs-up" />
<LikeButton cursor="pointer" />

// Custom cursor
<LikeButton cursor={{
  url: "data:image/svg+xml;...",
  hotspotX: 16,
  hotspotY: 16,
  fallback: "pointer"
}} />

Advanced Examples

Celebration Button

Perfect for achievements and milestones:

<LikeButton
  particlePreset="confetti"
  particleConfig={{
    count: 25,
    speed: 1000,
    distance: { min: 100, max: 150 }
  }}
  fillColor="#FFD700"
  size={100}
/>

Upvote Button

Reddit-style upvote with fountain effect:

<LikeButton
  particlePreset="fountain"
  particleConfig={{
    colors: ['#FF4500'],
    shape: 'star'
  }}
  fillColor="#FF4500"
  shape="rounded"
/>

Subtle Favorite

Gentle effect for favorites:

<LikeButton
  particlePreset="gentle"
  particleConfig={{
    colors: ['#FFB6C1', '#FFC0CB'],
    fadeOut: true
  }}
  fillColor="#FFB6C1"
/>

Custom Shape Particles

Create custom particle shapes:

import type { CustomParticleShape } from '@fmarlats/react-like-button';

const customDiamond: CustomParticleShape = {
  render: ({ size, color, className }) => (
    <svg width={size} height={size} className={className} viewBox="0 0 24 24">
      <path d="M12 2 L22 12 L12 22 L2 12 Z" fill={color} />
    </svg>
  )
};

<LikeButton particleConfig={{ shape: customDiamond }} />

API Reference

LikeButton Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | size | number | 80 | Button size in pixels | | fillColor | string | "#EF4444" | Fill color (hex or CSS color) | | waveColor | string | fillColor | Wave color (defaults to fillColor) | | maxClicks | number | Infinity | Maximum number of clicks allowed | | clicks | number | - | Controlled mode: current click count | | defaultClicks | number | 0 | Initial clicks for uncontrolled mode | | onChange | (clicks: number) => void | - | Called with new count (ideal for setClicks) | | onClick | (clicks: number, event) => void | - | Click handler with event access | | onRightClick | (clicks: number, event) => void | - | Right-click handler | | shape | ShapePreset \| CustomShape | "heart" | Button shape | | cursor | CursorPreset \| CustomCursor | "heart" | Cursor style | | styles | StyleOverrides | - | Custom style overrides | | renderIcon | (props) => ReactNode | - | Custom icon renderer | | minFillPercent | number | 5 | Minimum fill percentage | | showParticles | boolean | true | Enable/disable particle effects | | showWaves | boolean | true | Enable/disable wave animation on fill | | particlePreset | ParticlePreset | - | Particle effect preset | | particleConfig | ParticleConfig | - | Custom particle configuration |

ParticleConfig

| Property | Type | Default | Description | |----------|------|---------|-------------| | shape | ParticleShape | 'heart' | Particle shape | | colors | string[] | ['#EF4444', '#B9FF14', '#3B82F6'] | Particle colors | | count | number | 8 | Number of particles | | size | number \| Range | { min: 1.0, max: 1.5 } | Size multiplier | | speed | number | 500 | Animation duration (ms) | | distance | number \| Range | { min: 60, max: 100 } | Travel distance (px) | | spread | number | 360 | Spread angle (degrees) | | spreadOffset | number | 0 | Starting angle offset | | easing | string | 'cubic-bezier(0.22, 1, 0.36, 1)' | CSS easing | | fadeOut | boolean | true | Fade out animation |

ParticlePreset

| Preset | Shape | Count | Description | |--------|-------|-------|-------------| | 'burst' | ❤️ heart | 12 | Quick explosion in all directions | | 'fountain' | ⚫ circle | 10 | Upward spray effect | | 'confetti' | ◼️ square | 15 | Colorful celebration | | 'gentle' | ❤️ heart | 6 | Subtle floating effect | | 'fireworks' | ✨ sparkle | 16 | Explosive sparkles |

ParticleShape

  • 'heart' - Heart shape ❤️
  • 'star' - Star shape ⭐
  • 'circle' - Circle shape ⚫
  • 'square' - Square shape ◼️
  • 'sparkle' - Sparkle shape ✨
  • CustomParticleShape - Custom shape object

Examples

Check out the examples directory for more usage examples.

Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)
  • Mobile browsers (iOS Safari, Chrome Mobile)

Performance

The particle system is optimized for performance:

  • Particles are removed from DOM after animation
  • CSS transforms for smooth 60fps animations
  • Configurable particle count for performance tuning

Recommendations:

  • Use 5-20 particles for frequent interactions
  • Use 20-50 particles for special moments
  • Use 50+ particles sparingly (may impact performance on slower devices)

Accessibility

  • ARIA labels for screen readers
  • Keyboard support (Enter/Space to click)
  • Particles marked as decorative (aria-hidden="true")
  • Shift+Enter triggers right-click action for keyboard users

TypeScript

Full TypeScript support with comprehensive type definitions:

// Most common types
import type {
  LikeButtonProps,          // Component props
  IconRenderProps,          // Custom icon render function props
  ParticleConfig,           // Particle configuration
  CustomParticleShape,      // Custom particle shape
} from '@fmarlats/react-like-button';

// Hook types (for headless usage)
import type {
  UseLikeButtonOptions,     // Hook options
  UseLikeButtonReturn,      // Hook return type
} from '@fmarlats/react-like-button';

// Shape and cursor types
import type {
  Shape, ShapePreset, CustomShape,
  Cursor, CursorPreset, CustomCursor,
} from '@fmarlats/react-like-button';

// All particle types
import type {
  ParticlePreset, ParticleShape, ParticleShapePreset,
  ParticleShapeProps, Range,
} from '@fmarlats/react-like-button';

Changelog

v0.9.3 (Breaking Change)

⚠️ Breaking Change: Renamed localClicks to clicks

The localClicks prop has been renamed to clicks for clarity:

// Before
<LikeButton localClicks={clicks} onClick={(n) => setClicks(n)} />

// After
<LikeButton clicks={clicks} onClick={(n) => setClicks(n)} />

This also affects the useLikeButton hook:

  • Option: localClicksclicks
  • Return value: localClicksclicks
  • AriaLabelState.localClicksAriaLabelState.clicks

v0.9.0 (Breaking Change)

⚠️ Breaking Change for Tailwind Users

The Tailwind CSS version now requires importing a CSS file for animations and hover effects to work:

import { LikeButton } from '@fmarlats/react-like-button';
import '@fmarlats/react-like-button/like-button.css'; // NEW - Required

What changed:

  • Removed inline <style> tag injection for better performance and CSP compliance
  • Wave animations and hover/active states are now defined in an external CSS file
  • CSS custom properties are used for dynamic styling

Vanilla CSS users are not affected - continue importing @fmarlats/react-like-button/styles.css as before.

Contributing

Contributions are welcome! Please open an issue or pull request on GitHub.

License

MIT

Credits

Created by Florian MARLATS

Support