Skip to content

LynchzDEV/lynchz-confetti

Repository files navigation

React Confetti Shooter πŸŽ‰

A simple, lightweight React hook for creating confetti animations with directional shooting and intelligent auto-triggering. Perfect for celebrations, notifications, and interactive experiences.

✨ Features

  • 🎯 Directional shooting: Left, right, top, or center burst patterns
  • πŸ“ Source positioning: Confetti originates from any element position
  • ⚑ Auto-trigger: Automatic confetti on component mount with smart controls
  • πŸ”„ Loop mode: Continuous confetti celebrations with customizable intervals
  • 🎨 Customizable: Particle count, colors, timing, and physics
  • πŸ’‘ One-line usage: Just call triggerConfetti('direction')
  • πŸ“± Responsive: Works on all screen sizes
  • πŸ”§ TypeScript: Full type safety included
  • πŸͺΆ Lightweight: Zero dependencies (except React)

πŸš€ Installation

npm install react-confetti-shooter

Or with bun:

bun add react-confetti-shooter

πŸ“– Quick Start

Basic Manual Trigger

import React from 'react';
import { useConfetti } from 'react-confetti-shooter';

function MyComponent() {
  const { triggerConfetti, ConfettiRenderer } = useConfetti();

  return (
    <div>
      <ConfettiRenderer />
      
      <button onClick={() => triggerConfetti('center')}>
        Celebrate! πŸŽ‰
      </button>
    </div>
  );
}

Auto-Trigger Once (Welcome Screen)

import React from 'react';
import { useConfetti } from 'react-confetti-shooter';

function WelcomeComponent() {
  const { ConfettiRenderer } = useConfetti({
    autoTrigger: {
      enabled: true,
      direction: 'center',
      count: 100,
      delay: 1000 // Triggers once after 1 second
    }
  });

  return (
    <div>
      <ConfettiRenderer />
      <h1>Welcome! πŸŽ‰</h1>
    </div>
  );
}

Loop Mode (Party Time!)

import React from 'react';
import { useConfetti } from 'react-confetti-shooter';

function PartyComponent() {
  const { ConfettiRenderer } = useConfetti({
    autoTrigger: {
      enabled: true,
      direction: 'center',
      count: 75,
      delay: 500,
      loop: true,        // Enable continuous mode
      interval: 3000     // Trigger every 3 seconds
    }
  });

  return (
    <div>
      <ConfettiRenderer />
      <h1>🎊 Party Mode Activated! 🎊</h1>
    </div>
  );
}

πŸ”§ API Reference

useConfetti(options?)

Hook that manages confetti animations with intelligent auto-triggering.

Parameters:

  • options: UseConfettiOptions (optional) - Configuration options

Options:

  • autoTrigger: AutoTriggerOptions (optional) - Auto-trigger configuration
    • enabled: boolean - Whether to auto-trigger confetti
    • direction: Direction (optional, default: 'center') - Direction to shoot
    • count: number (optional, default: 50) - Number of particles
    • delay: number (optional, default: 0) - Initial delay in milliseconds
    • loop: boolean (optional, default: false) - Enable continuous triggering
    • interval: number (optional, default: 3000) - Time between loops (ms)

Returns:

triggerConfetti(direction, count?, sourceX?, sourceY?)

Manually triggers a confetti burst.

Parameters:

  • direction: 'left' | 'right' | 'top' | 'center' - Direction to shoot confetti
  • count: number (optional, default: 50) - Number of particles to create
  • sourceX: number (optional, default: center X) - X coordinate of confetti source
  • sourceY: number (optional, default: center Y) - Y coordinate of confetti source

ConfettiRenderer

React component that renders the confetti particles. Must be included in your JSX.

isAnimating

Boolean indicating if confetti animation is currently running.

particleCount

Number of active confetti particles currently on screen.

⚑ Auto-Trigger Modes

🎯 Once Mode (Default)

Perfect for welcome screens, success notifications, and one-time celebrations.

// Triggers once when component mounts
const { ConfettiRenderer } = useConfetti({
  autoTrigger: {
    enabled: true,
    direction: 'center',
    count: 100,
    delay: 1500 // Wait 1.5 seconds
  }
});

Behavior:

  • Triggers confetti once after the specified delay
  • Will not trigger again unless the component is remounted
  • Perfect for: Welcome screens, achievement unlocks, form submissions

πŸ”„ Loop Mode

Great for party modes, celebration pages, and ongoing festivities.

// Continuous confetti every few seconds
const { ConfettiRenderer } = useConfetti({
  autoTrigger: {
    enabled: true,
    direction: 'center',
    count: 50,
    delay: 1000,      // Initial delay
    loop: true,       // Enable looping
    interval: 4000    // Repeat every 4 seconds
  }
});

Behavior:

  • Initial trigger after delay milliseconds
  • Continues triggering every interval milliseconds
  • Stops when enabled is set to false or component unmounts
  • Perfect for: Party modes, celebration pages, background ambiance

🎨 Direction Examples

Left Shooter

const { triggerConfetti, ConfettiRenderer } = useConfetti();

<button onClick={() => triggerConfetti('left', 60)}>
  Shoot Left ← 
</button>

Right Shooter

<button onClick={() => triggerConfetti('right', 60)}>
  Shoot Right β†’
</button>

Top Shooter

<button onClick={() => triggerConfetti('top', 80)}>
  Shoot Up ↑
</button>

Center Explosion

<button onClick={() => triggerConfetti('center', 100)}>
  Explode πŸ’₯
</button>

🎯 Advanced Usage

Position-Based Shooting

function InteractiveConfetti() {
  const { triggerConfetti, ConfettiRenderer } = useConfetti();

  const handleButtonClick = (
    direction: Direction,
    event: React.MouseEvent<HTMLButtonElement>
  ) => {
    const rect = event.currentTarget.getBoundingClientRect();
    const sourceX = rect.left + rect.width / 2;
    const sourceY = rect.top + rect.height / 2;
    
    triggerConfetti(direction, 50, sourceX, sourceY);
  };

  return (
    <div className="grid grid-cols-2 gap-4">
      <ConfettiRenderer />
      
      {(['left', 'right', 'top', 'center'] as const).map(direction => (
        <button
          key={direction}
          onClick={(e) => handleButtonClick(direction, e)}
          className="p-4 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
        >
          {direction.charAt(0).toUpperCase() + direction.slice(1)}
        </button>
      ))}
    </div>
  );
}

Dynamic Auto-Trigger Control

function DynamicConfetti() {
  const [isPartyMode, setIsPartyMode] = useState(false);
  
  const { ConfettiRenderer, isAnimating } = useConfetti({
    autoTrigger: {
      enabled: isPartyMode,
      direction: 'center',
      count: 60,
      delay: 500,
      loop: true,
      interval: 2500
    }
  });

  return (
    <div>
      <ConfettiRenderer />
      
      <button 
        onClick={() => setIsPartyMode(!isPartyMode)}
        className={`px-6 py-3 rounded-lg text-white font-semibold ${
          isPartyMode ? 'bg-red-500' : 'bg-green-500'
        }`}
      >
        {isPartyMode ? '⏹️ Stop Party' : 'πŸŽ‰ Start Party Mode'}
      </button>
      
      <p className="mt-4">
        Status: {isPartyMode ? '🎊 Party Active' : '😴 Party Stopped'}
        {isAnimating && ' | ✨ Animating'}
      </p>
    </div>
  );
}

Multi-Stage Celebration

function MultiStageCelebration() {
  const [stage, setStage] = useState(0);
  
  const stages = [
    { direction: 'left', count: 30, delay: 500 },
    { direction: 'right', count: 30, delay: 1000 },
    { direction: 'center', count: 100, delay: 1500 }
  ];
  
  const { ConfettiRenderer } = useConfetti({
    autoTrigger: stage < stages.length ? {
      enabled: true,
      ...stages[stage]
    } : { enabled: false }
  });

  useEffect(() => {
    if (stage < stages.length - 1) {
      const timer = setTimeout(() => setStage(s => s + 1), 2000);
      return () => clearTimeout(timer);
    }
  }, [stage]);

  return (
    <div>
      <ConfettiRenderer />
      <div className="text-center p-8">
        <h2>🎊 Epic Celebration Sequence! 🎊</h2>
        <p>Stage {stage + 1} of {stages.length}</p>
        <button 
          onClick={() => setStage(0)}
          className="mt-4 px-4 py-2 bg-purple-500 text-white rounded"
        >
          πŸ”„ Restart Sequence
        </button>
      </div>
    </div>
  );
}

🎨 Styling & Customization

Built-in Colors

The library includes vibrant, celebration-ready colors:

  • #ff6b6b (Coral Red)
  • #4ecdc4 (Turquoise)
  • #45b7d1 (Sky Blue)
  • #ffd93d (Sunshine Yellow)
  • #ff8c42 (Orange Burst)
  • #a8e6cf (Mint Green)
  • #ff6f91 (Bubblegum Pink)

Animation Properties

  • Physics: Realistic gravity and motion
  • Rotation: Particles rotate as they fall
  • Cleanup: Automatic removal when off-screen
  • Performance: Optimized with requestAnimationFrame

πŸ“š Complete Examples

Success Page with Auto-Celebration

function SuccessPage() {
  const { ConfettiRenderer } = useConfetti({
    autoTrigger: {
      enabled: true,
      direction: 'center',
      count: 150,
      delay: 800
    }
  });
  
  return (
    <div className="min-h-screen flex items-center justify-center bg-green-50">
      <ConfettiRenderer />
      
      <div className="text-center p-8 bg-white rounded-xl shadow-lg">
        <div className="text-6xl mb-4">πŸŽ‰</div>
        <h1 className="text-3xl font-bold text-green-600 mb-2">Success!</h1>
        <p className="text-gray-600">Your payment has been processed.</p>
      </div>
    </div>
  );
}

Interactive Celebration Dashboard

function CelebrationDashboard() {
  const { triggerConfetti, ConfettiRenderer, particleCount, isAnimating } = useConfetti();
  const [autoMode, setAutoMode] = useState(false);
  
  const { ConfettiRenderer: AutoRenderer } = useConfetti({
    autoTrigger: {
      enabled: autoMode,
      direction: 'center',
      count: 40,
      loop: true,
      interval: 3000
    }
  });

  return (
    <div className="p-6 max-w-4xl mx-auto">
      <ConfettiRenderer />
      <AutoRenderer />
      
      <h1 className="text-4xl font-bold text-center mb-8">
        🎊 Confetti Control Center 🎊
      </h1>
      
      {/* Manual Controls */}
      <div className="bg-white rounded-lg p-6 shadow-md mb-6">
        <h2 className="text-xl font-semibold mb-4">Manual Triggers</h2>
        <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
          {(['left', 'right', 'top', 'center'] as const).map(direction => (
            <button
              key={direction}
              onClick={() => triggerConfetti(direction, 60)}
              className="py-3 px-4 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
              disabled={isAnimating}
            >
              {direction.charAt(0).toUpperCase() + direction.slice(1)}
            </button>
          ))}
        </div>
      </div>
      
      {/* Auto Mode */}
      <div className="bg-white rounded-lg p-6 shadow-md mb-6">
        <h2 className="text-xl font-semibold mb-4">Auto Mode</h2>
        <button
          onClick={() => setAutoMode(!autoMode)}
          className={`px-6 py-3 rounded-lg text-white font-semibold transition-colors ${
            autoMode ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600'
          }`}
        >
          {autoMode ? '⏹️ Stop Auto Mode' : 'πŸ”„ Start Auto Mode'}
        </button>
      </div>
      
      {/* Status */}
      <div className="bg-gray-100 rounded-lg p-4">
        <h3 className="font-semibold mb-2">Status</h3>
        <div className="grid grid-cols-2 gap-4 text-sm">
          <div>Active Particles: <span className="font-mono">{particleCount}</span></div>
          <div>Animation: <span className={`font-mono ${isAnimating ? 'text-green-600' : 'text-gray-500'}`}>
            {isAnimating ? 'Running' : 'Idle'}
          </span></div>
          <div>Auto Mode: <span className={`font-mono ${autoMode ? 'text-blue-600' : 'text-gray-500'}`}>
            {autoMode ? 'Enabled' : 'Disabled'}
          </span></div>
        </div>
      </div>
    </div>
  );
}

πŸ”„ TypeScript Support

Full TypeScript support with comprehensive type definitions:

import { 
  useConfetti, 
  Direction, 
  UseConfettiOptions, 
  AutoTriggerOptions 
} from 'react-confetti-shooter';

// Type-safe direction
const direction: Direction = 'center';

// Fully typed options
const options: UseConfettiOptions = {
  autoTrigger: {
    enabled: true,
    direction: 'center',
    count: 50,
    delay: 1000,
    loop: true,
    interval: 3000
  }
};

// Type-safe hook usage
const { triggerConfetti, ConfettiRenderer, isAnimating, particleCount } = useConfetti(options);

πŸ“± Performance & Compatibility

Browser Support

  • βœ… Chrome/Edge 60+
  • βœ… Firefox 55+
  • βœ… Safari 12+
  • βœ… Mobile browsers

Performance Features

  • Automatic particle cleanup when off-screen
  • Efficient requestAnimationFrame animations
  • Memory leak prevention with proper cleanup
  • Lightweight bundle size

Responsive Design

  • Adapts to all screen sizes
  • Viewport-relative positioning
  • Touch-friendly interactions

πŸ› οΈ Development

# Clone and setup
git clone https://github.com/LynchzDEV/lynchz-confetti.git
cd lynchz-confetti
bun install

# Build
bun run build

# Development
bun run dev

# Test locally
open test-example.html
open test-loop-example.html

🀝 Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

  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

πŸ“„ License

MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

Built with ❀️ for the React community. Perfect for adding joy, celebration, and interactive delight to your applications!


Ready to make your users smile? Let's shoot some confetti! 🎊✨

About

Just simple confetti that created in free time :D

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors