react-confetti-shooter
v1.2.3
Published
A simple, one-line React confetti library with directional shooting
Maintainers
Readme
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-shooterOr 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 configurationenabled:boolean- Whether to auto-trigger confettidirection:Direction(optional, default: 'center') - Direction to shootcount:number(optional, default: 50) - Number of particlesdelay:number(optional, default: 0) - Initial delay in millisecondsloop:boolean(optional, default: false) - Enable continuous triggeringinterval: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 confetticount:number(optional, default: 50) - Number of particles to createsourceX:number(optional, default: center X) - X coordinate of confetti sourcesourceY: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
delaymilliseconds - Continues triggering every
intervalmilliseconds - Stops when
enabledis 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
requestAnimationFrameanimations - 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.
- 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
📄 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! 🎊✨
