Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

partycles

jonathanleane0MIT1.2.6TypeScript support: included

๐ŸŽ‰ Delightful particle animations for React

react, animations, effects, rewards, confetti, sparkles, particles, celebration, fireworks, hearts, bubbles, snow, emoji, coins, petals, aurora, fireflies, galaxy, glitch, crystals, react-component, typescript, hooks, react-hooks, particle-effects, reward-animation, celebration-effects

readme

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.

โ†’ Try the Live Demo

npm version Bundle Size TypeScript License: MIT

โœจ 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(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 complete
  • isAnimating (boolean): Whether the animation is currently running
  • pause (function): Pauses the current animation
  • resume (function): Resumes a paused animation
  • replay (function): Stops current animation and starts a new one
  • isPaused (boolean): Whether the animation is currently paused
  • targetRef (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 emojis
  • emojiPresets.love - Heart emojis
  • emojiPresets.happy - Happy face emojis
  • emojiPresets.nature - Nature emojis
  • emojiPresets.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

  1. Unique IDs: Ensure each animated element has a unique ID
  2. Performance: Avoid triggering multiple animations simultaneously
  3. Accessibility: Provide alternative feedback for users who prefer reduced motion
  4. 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.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. 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

๐Ÿ“„ License

MIT ยฉ Jonathan Leane


Made with โค๏ธ by developers, for developers