npm.io
1.2.6 β€’ Published 1 year ago

partycles

Licence
MIT
Version
1.2.6
Deps
0
Size
481 kB
Vulns
0
Weekly
0
Stars
156

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): 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): 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