Confetti
Import
Section titled “Import”import { Confetti, confetti } from '@delightstack/components';The confetti function and Confetti component can be imported together. Types are also available:
import type { ConfettiOptions, ConfettiTarget, CannonOptions, RainOptions } from '@delightstack/components';Basic Usage
Section titled “Basic Usage”Programmatic API
Section titled “Programmatic API”The simplest way to fire confetti is with the confetti() function. No component mounting required.
burst and cannon are local effects — they erupt from a point. By default that point is wherever the user last clicked, so a confetti() fired from a click handler looks like it bursts out of the button that was pressed, with no extra code. fireworks, sides, and rain are global effects that fill the viewport and ignore the origin. See Targeting Local Effects to anchor a burst to a specific element instead.
View code
<script> import { confetti } from '@delightstack/components'; import { Button } from '@delightstack/components';</script>
<Button onclick={() => confetti()}>Burst</Button><Button outline onclick={() => confetti.fireworks()}>Fireworks</Button><Button outline onclick={() => confetti.sides()}>Sides</Button>Component API
Section titled “Component API”Mount <Confetti /> and control it with the active prop.
View code
<script> import { Confetti } from '@delightstack/components';
let celebrating = $state(false);</script>
<button onclick={() => celebrating = true}>Celebrate!</button><Confetti active={celebrating} onend={() => celebrating = false} />Examples
Section titled “Examples”Customized Burst
Section titled “Customized Burst”View code
<script> import { confetti } from '@delightstack/components';
function celebrate() { confetti({ particle_count: 100, spread: 70, origin: { x: 0.5, y: 0.6 }, colors: ['#ff0000', '#00ff00', '#0000ff'], }); }</script>
<button onclick={celebrate}>Custom Burst</button>Preset Animations
Section titled “Preset Animations”All presets are available as methods on the confetti function.
View code
<script> import { confetti } from '@delightstack/components';</script>
<!-- Single burst (same as confetti()) --><button onclick={() => confetti.burst()}>Burst</button>
<!-- Continuous cannon stream --><button onclick={() => confetti.cannon({ duration: 3000 })}>Cannon</button>
<!-- Multiple random bursts --><button onclick={() => confetti.fireworks()}>Fireworks</button>
<!-- Bursts from both screen edges --><button onclick={() => confetti.sides()}>Sides</button>
<!-- Gentle particles falling from top --><button onclick={() => confetti.rain({ duration: 4000 })}>Rain</button>Stopping Continuous Effects
Section titled “Stopping Continuous Effects”confetti.cannon() and confetti.rain() return a stop() function. You can also use confetti.stop() to stop all active animations.
View code
<script> import { confetti } from '@delightstack/components';
let stopCannon: (() => void) | undefined;
function startCannon() { stopCannon = confetti.cannon({ duration: 10000 }); }</script>
<button onclick={startCannon}>Start Cannon</button><button onclick={() => stopCannon?.()}>Stop Cannon</button><button onclick={() => confetti.stop()}>Stop All</button>Component with Presets
Section titled “Component with Presets”View code
<script> import { Confetti } from '@delightstack/components';
let celebrating = $state(false);</script>
<button onclick={() => celebrating = true}>Complete Task</button><Confetti active={celebrating} preset="cannon" duration={2000} onend={() => celebrating = false}/>Targeting Local Effects
Section titled “Targeting Local Effects”Local effects (burst, cannon) erupt from the last clicked point automatically, so the first button below needs no configuration. To anchor a burst somewhere else, pass a target — a DOM element, a CSS selector, or a pointer/mouse event. It takes precedence over the last click and over origin.
View code
<script> import { confetti } from '@delightstack/components';
let box;</script>
<!-- Auto-targets the click --><button onclick={() => confetti.burst()}>Burst from me</button>
<!-- Explicit target: an element ref (a selector string or event also work) --><button onclick={() => confetti.burst({ target: box })}>Burst from the box</button><div bind:this={box}></div>Programmatic API Reference
Section titled “Programmatic API Reference”confetti(options?)
Section titled “confetti(options?)”Fire a single burst of confetti. Shorthand for confetti.burst().
confetti.burst(options?)
Section titled “confetti.burst(options?)”Single explosion. A local effect: it erupts from target, then origin, then the last clicked point, falling back to bottom-center.
confetti.cannon(options?): () => void
Section titled “confetti.cannon(options?): () => void”Continuous stream of particles from a single point. A local effect that honors target/origin just like burst. Returns a stop() function.
confetti.fireworks(options?)
Section titled “confetti.fireworks(options?)”Multiple large timed bursts from random positions across the viewport. A global effect; ignores target/origin.
confetti.sides(options?)
Section titled “confetti.sides(options?)”Simultaneous bursts from both screen edges, angled inward. A global effect; ignores target/origin.
confetti.rain(options?): () => void
Section titled “confetti.rain(options?): () => void”Gentle particles falling from the top. Returns a stop() function.
confetti.stop()
Section titled “confetti.stop()”Stop all active animations and clean up the canvas.
Component props for <Confetti />. The defaults below apply to the burst preset; any prop left unset falls back to the chosen preset’s own default (for example, fireworks uses a larger particle_count).
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | false | Trigger confetti when set to true |
preset | 'burst' | 'cannon' | 'fireworks' | 'sides' | 'rain' | 'burst' | Animation preset |
particle_count | number | 50 | Number of particles (max 500) |
spread | number | 60 | Spread angle in degrees |
start_velocity | number | 30 | Initial launch speed |
decay | number | 0.94 | Velocity decay per frame (0-1) |
gravity | number | 1 | Gravity multiplier |
drift | number | 0 | Horizontal drift |
ticks | number | 200 | Frames before particle fades |
origin | { x: number, y: number } | last click | Origin point for local effects (0-1 normalized) |
target | ConfettiTarget | — | Anchor a local effect to an element, selector, or event |
colors | string[] | Rainbow palette | Particle color palette |
scalar | number | 1 | Particle size multiplier |
z_index | number | 1000 | Canvas z-index |
duration | number | 3000 | Duration for cannon/rain presets (ms) |
disable_for_reduced_motion | boolean | true | Respect prefers-reduced-motion |
id | string | auto | Element ID |
class | string | '' | Additional CSS classes |
Events
Section titled “Events”| Event | Detail | Description |
|---|---|---|
onend | () => void | Called when all particles have finished animating |
// Anchor for a local effect: an element, a CSS selector, or a pointer/mouse eventtype ConfettiTarget = Element | string | MouseEvent;
interface ConfettiOptions { particle_count?: number; spread?: number; start_velocity?: number; decay?: number; gravity?: number; drift?: number; ticks?: number; origin?: { x: number; y: number }; target?: ConfettiTarget; colors?: string[]; scalar?: number; z_index?: number; angle?: number;}
interface CannonOptions extends ConfettiOptions { interval?: number; duration?: number;}
interface RainOptions extends ConfettiOptions { duration?: number;}Accessibility
Section titled “Accessibility”- Canvas element has
aria-hidden="true"(purely decorative) pointer-events: noneon the canvas so it never blocks interaction- Respects
prefers-reduced-motionby default — when active,confetti()is a no-op - No sound effects or other sensory output