Confetti
Add celebratory confetti effects to your application with customizable particles, colors, and physics. Built with @neoconfetti/svelte, this component provides both a flexible wrapper component and a convenient button component.
npx shadcn-svelte add https://animations.sikandar.in/magic/confetti
Installation
Install Dependencies
This component requires the neoconfetti library:
npm install @neoconfetti/svelte
Components
This package exports two components:
- Confetti - A wrapper component that triggers confetti around child elements
- ConfettiButton - A pre-styled button with built-in confetti trigger
Usage
Confetti Wrapper
Wrap any element to add confetti effects:
<script>
import { Confetti } from "$lib/components/magic-ui/confetti";
import { Button } from "$lib/components/ui/button";
let active = $state(false);
function fire() {
active = false;
setTimeout(() => {
active = true;
}, 10);
}
</script>
<Confetti {active}>
<Button onclick={fire}>Fire Confetti</Button>
</Confetti>
Pre-built button with confetti effect:
<script>
import { ConfettiButton } from "$lib/components/magic-ui/confetti";
</script>
<ConfettiButton>Click Me!</ConfettiButton>
Custom Confetti Options
<script>
import { Confetti } from "$lib/components/magic-ui/confetti";
import { Button } from "$lib/components/ui/button";
let active = $state(false);
const confettiOptions = {
particleCount: 100,
force: 0.7,
colors: ["#ff0000", "#00ff00", "#0000ff"],
duration: 3000,
};
function fire() {
active = false;
setTimeout(() => {
active = true;
}, 10);
}
</script>
<Confetti {active} options={confettiOptions}>
<Button onclick={fire}>Celebrate!</Button>
</Confetti>
<script>
import { ConfettiButton } from "$lib/components/magic-ui/confetti";
</script>
<ConfettiButton
class="bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600"
options={{ particleCount: 75, force: 0.6 }}
>
🎉 Celebrate!
</ConfettiButton>
With Custom Click Handler
<script>
import { ConfettiButton } from "$lib/components/magic-ui/confetti";
function handleSuccess() {
console.log("Celebration triggered!");
// Additional logic here
}
</script>
<ConfettiButton onclick={handleSuccess}>
Complete Task
</ConfettiButton>
Props
Confetti Component
Controls when the confetti effect is triggered. Set to false then true to fire confetti. Use a small timeout (10ms) between state changes to ensure the animation triggers.
options
Partial<ConfettiOptions>
default:"{}"
Configuration options for the confetti effect. See Confetti Options below for available properties.
Additional CSS classes to apply to the wrapper container.
Additional CSS classes to apply specifically to the confetti effect container.
children
Snippet
default:"undefined"
Child elements to wrap. The confetti will be positioned relative to this container.
options
Partial<ConfettiOptions>
default:"{}"
Additional CSS classes to customize the button appearance. Default styling includes blue background with hover effects.
onclick
function
default:"undefined"
Click event handler. Called after confetti is triggered. Receives the click event as parameter.
children
Snippet
default:"'Click Me!'"
Button content. If not provided, displays “Click Me!” as default text.
All other standard HTML button attributes (disabled, type, aria-label, etc.) are supported.
Confetti Options
The options prop accepts any properties from @neoconfetti/svelte. Common options include:
Number of confetti particles to generate.
Initial velocity/force of the particles. Range: 0-1.
Height of the confetti stage area in pixels.
Width of the confetti stage area in pixels.
colors
string[]
default:"['#ff0000', '#00ff00', '#0000ff']"
Array of color hex codes for the confetti particles.
Duration of the confetti animation in milliseconds.
Size of individual confetti particles in pixels.
particleShape
'mix' | 'circles' | 'rectangles'
default:"'mix'"
Shape of the confetti particles.
For the complete list of options, see the @neoconfetti/svelte documentation.
Examples
Success Notification
<script>
import { Confetti } from "$lib/components/magic-ui/confetti";
import { toast } from "svelte-sonner";
let showConfetti = $state(false);
async function handleSubmit() {
// Submit form logic
await submitForm();
// Trigger confetti on success
showConfetti = false;
setTimeout(() => {
showConfetti = true;
toast.success("Form submitted successfully!");
}, 10);
}
</script>
<Confetti
active={showConfetti}
options={{ particleCount: 100, force: 0.8 }}
class="fixed inset-0 pointer-events-none"
>
<button onclick={handleSubmit}>Submit Form</button>
</Confetti>
Themed Confetti
<script>
import { ConfettiButton } from "$lib/components/magic-ui/confetti";
const valentinesOptions = {
particleCount: 80,
colors: ["#FF1461", "#FF69B4", "#FF0080", "#FFFFFF"],
particleShape: "circles",
force: 0.6,
};
</script>
<ConfettiButton
options={valentinesOptions}
class="bg-pink-500 hover:bg-pink-600"
>
❤️ Send Love
</ConfettiButton>
Multiple Confetti Bursts
<script>
import { Confetti } from "$lib/components/magic-ui/confetti";
let active = $state(false);
function fireBurst() {
// Fire multiple times with delays
for (let i = 0; i < 3; i++) {
setTimeout(() => {
active = false;
setTimeout(() => {
active = true;
}, 10);
}, i * 500);
}
}
</script>
<Confetti {active} options={{ particleCount: 50, force: 0.7 }}>
<button onclick={fireBurst}>Triple Burst! 🎊</button>
</Confetti>
Achievement Unlocked
<script>
import { Confetti } from "$lib/components/magic-ui/confetti";
let active = $state(false);
let score = $state(0);
function addPoints() {
score += 10;
// Trigger confetti every 100 points
if (score % 100 === 0) {
active = false;
setTimeout(() => {
active = true;
}, 10);
}
}
</script>
<Confetti
{active}
options={{
particleCount: 150,
force: 0.8,
colors: ["#FFD700", "#FFA500", "#FF8C00"],
}}
class="fixed inset-0 pointer-events-none z-50"
>
<div>
<p>Score: {score}</p>
<button onclick={addPoints}>Add Points</button>
</div>
</Confetti>
Technical Details
How It Works
The confetti effect is triggered by toggling the active prop from false to true. The component uses the @neoconfetti/svelte action which creates and animates confetti particles using CSS transforms and transitions.
Positioning
By default, confetti originates from the center-top of the wrapper container. Use the confettiClass prop to adjust positioning:
<Confetti
{active}
confettiClass="left-1/4 top-1/2"
>
<button>Custom Position</button>
</Confetti>
The confetti animation is GPU-accelerated and performs well even with high particle counts. However, for optimal performance on mobile devices, consider reducing particleCount to 50 or fewer.
Tips
Always use a small timeout (10ms) when toggling the active state to ensure the confetti animation triggers properly. Simply setting it to true without first setting it to false won’t trigger the effect.
For full-screen confetti effects, wrap your entire page in the Confetti component with class="fixed inset-0 pointer-events-none" to position it above all content without blocking interactions.
Avoid triggering confetti too frequently, as it can be distracting and reduce the impact of the effect. Reserve it for meaningful moments like completing important actions.
Accessibility
The confetti effect is purely decorative and doesn’t interfere with keyboard navigation or screen readers. However, consider the following:
- Don’t rely solely on confetti to communicate important information
- Pair confetti with text confirmations or toast notifications
- Consider users with motion sensitivity - provide a way to disable animations if possible