@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.
Maintainers
Keywords
Readme
React Like Button
| Custom heart with on complete state | Classic button | Like shaped cursor | Gold stars particle |
|--------|--------|--------|--------|
|
|
|
|
|
| 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-buttonQuick 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:
localClicks→clicks - Return value:
localClicks→clicks AriaLabelState.localClicks→AriaLabelState.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 - RequiredWhat 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
