Confetti

DOM-based particle burst — no canvas, no third-party lib, no extra runtime dep. The component renders an invisible anchor; call ref.current.fire() to spawn a fresh particle layer at that anchor. Each particle follows projectile motion (initial velocity + gravity), with randomised colour, size, and rotation. GSAP-backed.

Each click mounts a fresh particle layer at the button. Particles clean themselves up after the lifetime expires.

Usage

import { Confetti, ConfettiHandle, Button } from '@bwo-ui/react';
import { useRef } from 'react';

const ref = useRef<ConfettiHandle>(null);

<Confetti ref={ref} count={80} spread={360}>
  <Button onClick={() => ref.current?.fire()}>🎉</Button>
</Confetti>

// Override per-fire — for "wins go faster, losses go slower" etc.
ref.current?.fire({ velocity: 800, colors: ['#16a34a'] });

Props

PropTypeDefaultDescription
countnumber60Number of particles per fire.
spreadnumber90Spread arc in degrees. 360 = burst in all directions.
anglenumber0Origin angle in degrees (0 = up).
velocitynumber560Initial velocity in pixels per second.
gravitynumber1400Downward pull on particles (px / s²).
durationnumber1.6Particle lifetime in seconds.
size[min, max][6, 12]Particle size range in pixels.
colorsstring[]Palette to randomise from.
origin{ x: number; y: number }Origin offset within the anchor (default = centre).
zIndexnumber9999Z-index for the particle layer.