Partycles ๐
A lightweight, performant React library for adding delightful animation effects to your applications. Perfect for celebrating user achievements, form submissions, or any moment worth highlighting.
โจ Features
- ๐ฏ Simple API - Just one hook to rule them all
- ๐จ 23 Beautiful Animations - Confetti, sparkles, hearts, stars, fireworks, bubbles, snow, emoji, coins, petals, aurora, fireflies, paint, balloons, galaxy, glitch, magicdust, crystals, leaves, mortar, bokeh, ribbons, and geometric
- ๐ฆ Tiny Bundle - Zero dependencies, optimized for performance
- ๐ Performant - Optimized animations using requestAnimationFrame
- ๐ฎ Full Control - Customize colors, particle count, physics, and more
- ๐ฑ Mobile Optimized - Automatic performance optimizations for mobile devices
- ๐ง TypeScript Support - Fully typed for excellent DX
- โก React 18 Ready - Built with the latest React features
๐ฆ Installation
npm install partycles
# or
yarn add partycles
# or
pnpm add partycles
๐ Quick Start
import { useRef } from 'react';
import { useReward } from 'partycles';
function App() {
const buttonRef = useRef<HTMLButtonElement>(null);
const { reward, isAnimating } = useReward(buttonRef, 'confetti');
return (
<button ref={buttonRef} onClick={reward} disabled={isAnimating}>
Click me for a surprise! ๐
</button>
);
}
That's it! No configuration needed - it just works. ๐
Using String IDs (Legacy)
For backward compatibility, you can still use element IDs:
const { reward, isAnimating } = useReward('my-button', 'confetti');
<button id="my-button" onClick={reward}>
Click me! ๐
</button>
๐ค Why Partycles?
- Zero Dependencies - No bloat, just pure React code
- One Hook - Simple
useReward
hook handles everything - 23 Animations - From confetti to modern geometric bursts, we've got you covered
- Fully Typed - Great TypeScript support out of the box
- Customizable - Tweak colors, physics, particle count, and more
- Performant - Optimized animations that won't slow down your app
๐ API Reference
useReward(targetRef, animationType, config?)
(Recommended)
useReward(elementId, animationType, config?)
(Legacy)
The main hook for creating reward animations.
Parameters
targetRef
(RefObject<HTMLElement>): A React ref to the element to animate from (recommended)elementId
(string): The ID of the element to animate from (legacy, for backward compatibility)animationType
(string): One of:'confetti'
,'sparkles'
,'hearts'
,'stars'
,'fireworks'
,'bubbles'
,'snow'
,'emoji'
,'coins'
,'petals'
,'aurora'
,'fireflies'
,'paint'
,'balloons'
,'galaxy'
,'glitch'
,'magicdust'
,'crystals'
,'leaves'
,'mortar'
,'bokeh'
,'ribbons'
,'geometric'
config
(optional): Animation configuration object
Returns
reward
(function): Triggers the animation, returns a Promise that resolves when completeisAnimating
(boolean): Whether the animation is currently runningpause
(function): Pauses the current animationresume
(function): Resumes a paused animationreplay
(function): Stops current animation and starts a new oneisPaused
(boolean): Whether the animation is currently pausedtargetRef
(RefObject<HTMLElement>): The ref object (only returned when using ref-based API)
Configuration Options
interface AnimationConfig {
particleCount?: number; // Number of particles (default: varies by animation)
spread?: number; // Spread angle in degrees (default: 50)
startVelocity?: number; // Initial velocity (default: 45)
decay?: number; // Velocity decay rate (default: 0.9)
lifetime?: number; // Particle lifetime (default: 100)
colors?: string[]; // Array of colors (or emojis for 'emoji' type)
elementSize?: number; // Size of particles in pixels
duration?: number; // Total animation duration
physics?: {
gravity?: number; // Gravity force (default: 0.5)
wind?: number; // Horizontal wind force (default: 0)
friction?: number; // Air friction (default: 0.99)
};
// NEW: Optional enhanced effects
effects?: {
flutter?: boolean; // Paper-like floating for confetti
twinkle?: boolean; // Brightness variation for stars/sparkles
pulse?: boolean; // Heartbeat effect for hearts
spin3D?: boolean; // 3D rotation for coins
wobble?: boolean; // Realistic wobble for bubbles
windDrift?: boolean; // Horizontal drift for snow/leaves
};
}
๐จ Animation Types
Confetti ๐
Classic celebration effect with colorful paper pieces.
const buttonRef = useRef<HTMLButtonElement>(null);
const { reward } = useReward(buttonRef, 'confetti', {
particleCount: 30,
spread: 60,
colors: ['#ff0000', '#00ff00', '#0000ff'],
// NEW: Enable paper flutter effect
effects: { flutter: true }
});
Sparkles โจ
Twinkling star effect perfect for magical moments.
const { reward } = useReward('buttonId', 'sparkles', {
particleCount: 20,
elementSize: 15
});
Hearts ๐
Floating hearts for likes, favorites, or love actions.
const { reward } = useReward('buttonId', 'hearts', {
particleCount: 15,
colors: ['#ff1744', '#e91e63', '#ff4569']
});
Stars โญ
Shooting stars effect for achievements and ratings.
const { reward } = useReward('buttonId', 'stars', {
particleCount: 25,
physics: { gravity: 0.3 }
});
Fireworks ๐
Explosive celebration for major milestones.
const { reward } = useReward('buttonId', 'fireworks', {
particleCount: 40,
spread: 180
});
Bubbles ๐ซง
Gentle floating bubbles for calm, playful effects.
const { reward } = useReward('buttonId', 'bubbles', {
particleCount: 20,
physics: { gravity: -0.1 }
});
Snow โ๏ธ
Peaceful falling snowflakes for winter themes.
const { reward } = useReward('buttonId', 'snow', {
particleCount: 50,
physics: { gravity: 0.05, wind: 0.1 }
});
Emoji ๐
Customizable emoji explosions for any mood.
import { useReward, emojiPresets } from 'partycles';
// Use built-in presets
const { reward } = useReward('buttonId', 'emoji', {
colors: emojiPresets.celebration // ๐๐๐ฅณ๐๐๐พ๐ฅ๐
});
// Or custom emojis
const { reward } = useReward('buttonId', 'emoji', {
particleCount: 30,
colors: ['๐', '๐', '๐', '๐', 'โจ']
});
Available emoji presets:
emojiPresets.celebration
- Party emojisemojiPresets.love
- Heart emojisemojiPresets.happy
- Happy face emojisemojiPresets.nature
- Nature emojisemojiPresets.food
- Food emojis
Coins ๐ฐ
Falling coins for rewards and achievements.
const { reward } = useReward('buttonId', 'coins', {
particleCount: 25,
physics: { gravity: 0.5 }
});
Petals ๐ธ
Delicate flower petals floating in the wind.
const { reward } = useReward('buttonId', 'petals', {
particleCount: 40,
physics: { gravity: 0.08, wind: 0.15 }
});
Aurora ๐
Northern lights effect with flowing ribbons.
const { reward } = useReward('buttonId', 'aurora', {
particleCount: 15,
elementSize: 100
});
Fireflies โจ
Glowing fireflies with organic movement.
const { reward } = useReward('buttonId', 'fireflies', {
particleCount: 20,
lifetime: 300
});
Paint ๐จ
Paint splatter effect for creative actions.
const { reward } = useReward('buttonId', 'paint', {
particleCount: 25,
startVelocity: 35
});
Balloons ๐
Floating balloons with realistic physics.
const { reward } = useReward('buttonId', 'balloons', {
particleCount: 15,
lifetime: 400
});
Galaxy ๐
Spiral star formation with twinkling effects.
const { reward } = useReward('buttonId', 'galaxy', {
particleCount: 60,
spread: 200
});
Glitch ๐บ
Digital glitch effect for tech themes.
const { reward } = useReward('buttonId', 'glitch', {
particleCount: 30,
elementSize: 40
});
Magic Dust โจ
Magical sparkling dust particles.
const { reward } = useReward('buttonId', 'magicdust', {
particleCount: 35,
colors: ['#9c27b0', '#673ab7', '#3f51b5']
});
Crystals ๐
Shimmering crystal fragments.
const { reward } = useReward('buttonId', 'crystals', {
particleCount: 20,
elementSize: 25
});
Leaves ๐
Falling autumn leaves with natural movement.
const { reward } = useReward('buttonId', 'leaves', {
particleCount: 30,
physics: { gravity: 0.05, wind: 0.2 }
});
Mortar ๐ฅ
Explosive mortar-style bursts with galaxy-like explosions.
const { reward } = useReward('buttonId', 'mortar', {
particleCount: 2,
spread: 45,
physics: { gravity: 0.35 }
});
Bokeh ๐ฎ
Soft, dreamy light orbs with depth-of-field effect. Inspired by photography bokeh.
const { reward } = useReward('buttonId', 'bokeh', {
particleCount: 25,
elementSize: 40,
lifetime: 400,
physics: { gravity: -0.02 }
});
๐ก Examples
Animation Controls
Control your animations with pause, resume, and replay:
import { useRef } from 'react';
import { useReward } from 'partycles';
function ControlledAnimation() {
const buttonRef = useRef<HTMLButtonElement>(null);
const { reward, isAnimating, pause, resume, replay, isPaused } = useReward(
buttonRef,
'confetti',
{ particleCount: 50 }
);
return (
<div>
<button ref={buttonRef} onClick={reward}>
Start Animation
</button>
<button onClick={pause} disabled={!isAnimating || isPaused}>
Pause
</button>
<button onClick={resume} disabled={!isAnimating || !isPaused}>
Resume
</button>
<button onClick={replay}>
Replay
</button>
<p>Status: {isAnimating ? (isPaused ? 'Paused' : 'Playing') : 'Idle'}</p>
</div>
);
}
Promise-based Completion
Chain actions after animations complete:
const { reward } = useReward(buttonRef, 'confetti');
const handleSuccess = async () => {
await reward(); // Wait for animation to complete
console.log('Animation finished!');
// Navigate, show message, etc.
};
### Form Submission Success
```tsx
function ContactForm() {
const { reward } = useReward('submit-btn', 'confetti');
const handleSubmit = async (e) => {
e.preventDefault();
const success = await submitForm();
if (success) {
reward();
}
};
return (
<form onSubmit={handleSubmit}>
{/* form fields */}
<button id="submit-btn" type="submit">
Send Message
</button>
</form>
);
}
Like Button with Hearts
function LikeButton() {
const [liked, setLiked] = useState(false);
const { reward } = useReward('like-btn', 'hearts', {
particleCount: 10,
elementSize: 20
});
const handleLike = () => {
setLiked(!liked);
if (!liked) {
reward();
}
};
return (
<button id="like-btn" onClick={handleLike}>
{liked ? 'โค๏ธ' : '๐ค'} Like
</button>
);
}
Achievement Unlocked
function Achievement({ unlocked, name }) {
const { reward } = useReward('achievement', 'fireworks', {
particleCount: 50,
spread: 120
});
useEffect(() => {
if (unlocked) {
reward();
}
}, [unlocked, reward]);
return (
<div id="achievement" className="achievement-badge">
๐ {name}
</div>
);
}
โจ Enhanced Effects (v1.1.5+)
Make animations more realistic with optional effects:
// Confetti with paper flutter
const { reward } = useReward('confetti-btn', 'confetti', {
effects: { flutter: true }
});
// Stars with twinkling
const { reward } = useReward('star-btn', 'stars', {
effects: { twinkle: true }
});
// Hearts with pulse/heartbeat
const { reward } = useReward('heart-btn', 'hearts', {
effects: { pulse: true }
});
// Coins with 3D spin
const { reward } = useReward('coin-btn', 'coins', {
effects: { spin3D: true }
});
// Snow with wind drift
const { reward } = useReward('snow-btn', 'snow', {
effects: { windDrift: true }
});
// Bubbles with wobble
const { reward } = useReward('bubble-btn', 'bubbles', {
effects: { wobble: true }
});
// Combine multiple effects
const { reward } = useReward('magic-btn', 'sparkles', {
effects: {
twinkle: true,
// Other effects work too!
},
physics: {
gravity: 0.2,
wind: 0.1
}
});
๐ฏ Best Practices
- Unique IDs: Ensure each animated element has a unique ID
- Performance: Avoid triggering multiple animations simultaneously
- Accessibility: Provide alternative feedback for users who prefer reduced motion
- Mobile: Partycles automatically optimizes for mobile devices
// Respect user preferences
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const { reward } = useReward('buttonId', 'confetti', {
particleCount: prefersReducedMotion ? 0 : 30
});
๐ฑ Mobile Optimization
Partycles automatically detects mobile devices and optimizes performance:
- Reduced particle counts (60% of desktop)
- Smaller particle sizes (80% of desktop)
- Shorter lifetimes (80% of desktop)
- Frame skipping for smoother performance
- Tab visibility detection to pause when inactive
You can also manually check for mobile devices:
import { isMobileDevice, optimizeConfigForMobile } from 'partycles';
if (isMobileDevice()) {
// Custom mobile logic
}
// Or manually optimize a config
const mobileConfig = optimizeConfigForMobile({
particleCount: 100,
elementSize: 30
});
๐ง Advanced Usage
Custom Physics
const { reward } = useReward('buttonId', 'confetti', {
physics: {
gravity: 0.2, // Lower gravity = floatier particles
wind: 0.1, // Positive = blow right, negative = blow left
friction: 0.95 // Higher = more air resistance
}
});
Dynamic Configuration
function DynamicReward() {
const [intensity, setIntensity] = useState(1);
const { reward } = useReward('buttonId', 'confetti', {
particleCount: 30 * intensity,
spread: 50 + (20 * intensity),
startVelocity: 45 * intensity
});
return (
<>
<input
type="range"
min="0.5"
max="2"
step="0.1"
value={intensity}
onChange={(e) => setIntensity(parseFloat(e.target.value))}
/>
<button id="buttonId" onClick={reward}>
Celebrate!
</button>
</>
);
}
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
๐ Changelog
v1.2.6 (Latest)
- ๐ Added new
ribbons
animation with wavy streamers and gradient effects - ๐ท Added new
geometric
animation with modern shapes (triangles, squares, diamonds, hexagons, stars) - โจ Both animations feature satisfying physics inspired by the popular confetti effect
- ๐๏ธ Removed fire animation as it didn't work well as a burst effect
v1.2.3
- ๐ฎ Updated bokeh animation defaults for better visual impact
- ๐ Increased default particle count from 25 to 50
- โฑ๏ธ Reduced lifetime from 400 to 200 for snappier animations
- ๐ฏ Adjusted physics for more natural movement
v1.2.2
- ๐ฎ Added new
bokeh
animation with soft, dreamy light orbs - ๐ Added credits section to acknowledge contributors
- ๐ฑ Optimized bokeh effect for smooth performance
v1.2.1
- ๐ Added new
mortar
animation with galaxy-style explosions - ๐ Fixed particle rendering issues with dynamic particle creation
- ๐จ Updated emoji assignments for better consistency (fireflies: ๐, coins: ๐ฐ)
- โก Optimized mortar explosion performance for mobile devices
- ๐ง Improved animation manager to handle particles created during updates
v1.1.5
- โจ Added optional enhanced effects (flutter, twinkle, pulse, spin3D, wobble, windDrift)
- ๐ฑ Improved mobile performance with automatic optimizations
v1.1.3
- ๐ Added automatic mobile performance optimizations
- ๐ Fixed Safari compatibility issues
- ๐ฆ Streamlined bundle size by removing 7 animations
- ๐ง Fixed CI/CD pipeline and npm publishing
v1.0.0
- ๐ Initial release with 26 animations
๐ Credits
- Bokeh effect inspired by Sergio A. Carrasco Chavez's beautiful bokeh implementation
๐ License
MIT ยฉ Jonathan Leane
Made with โค๏ธ by developers, for developers