better-react-confetti · v0.1.0

React confetti without a DOM node for every particle.

better-react-confetti is a lightweight, canvas-based React confetti component for success states, launches, milestones, and one-time celebration bursts. It supports React 18 and React 19, ships TypeScript declarations, and keeps animation work in one canvas and one requestAnimationFrame loop.

  • One canvas
  • React 18 + 19
  • TypeScript types
  • Built-in shapes

Live React confetti demo

This is a one-time burst with 120 particles, five colors, and recycling disabled. Trigger it again to remount the component and start a fresh celebration.

You did it!

A little feedback for the moments that matter.

Why use canvas for React confetti?

A DOM-based confetti effect can create several animated elements for every particle. That is flexible, but the browser still has to style, lay out, animate, and retain every node. The cost grows with the size of the burst.

better-react-confetti keeps the hot path outside React. React renders one wrapper and one canvas, while typed arrays hold particle state and a single animation loop updates position, velocity, rotation, and recycling. A ResizeObserver keeps the canvas matched to its container.

Comparison between canvas-based and DOM-based React confetti
Considerationbetter-react-confettiDOM-based confetti
RenderingOne canvas and one animation loopAnimated element trees for individual particles
Shape supportRectangle, circle, and triangleBetter suited to arbitrary React or SVG shapes
Best fitControlled bursts with predictable particle countsEffects that need custom DOM content per particle

Install better-react-confetti

Choose the package manager used by your React project.

pnpm add better-react-confetti
npm install better-react-confetti
yarn add better-react-confetti
bun add better-react-confetti

React confetti example

Place the component inside a positioned container. Set recycle to false for a finite burst, and remount it when another celebration should begin.

import Confetti, { Circle, Rectangle, Triangle } from "better-react-confetti";

export function SuccessMoment() {
  const shapes = [
    <Rectangle key="rectangle" color="#f0c66a" />,
    <Circle key="circle" color="#ef5da8" />,
    <Triangle key="triangle" color="#34a7dc" />,
  ];

  return (
    <div className="celebration-stage">
      <Confetti
        total={140}
        Component={shapes}
        gravity={0.28}
        speed={1.1}
        recycle={false}
        aria-hidden="true"
      />
      <p>Payment complete</p>
    </div>
  );
}

React confetti component API

Standard div attributes also pass through to the wrapper, so className, style, and accessibility attributes can be applied normally.

better-react-confetti component properties
PropDefaultPurpose
total90Sets the number of particles in the celebration.
ComponentBuilt-in mixAccepts Rectangle, Circle, Triangle, or an array of those built-in shapes.
colorsFive-color paletteSets the palette used when Component is omitted.
gravity0.22Controls downward acceleration.
wind0Adds horizontal acceleration.
speed1Scales the initial particle velocity.
recycletrueRespawns particles after they leave the stage.

Use celebration effects accessibly

Confetti should reinforce a success message, not replace it. Keep a visible text confirmation in the interface, mark the decorative canvas as aria-hidden, and do not make users wait for the animation before continuing.

The component does not make product decisions about reduced motion. Check the user's prefers-reduced-motion setting before rendering a burst, or provide an equivalent quiet success state.

import { useEffect, useState } from "react";

function useReducedMotion() {
  const [reduceMotion, setReduceMotion] = useState(false);

  useEffect(() => {
    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
    const update = () => setReduceMotion(media.matches);

    update();
    media.addEventListener("change", update);
    return () => media.removeEventListener("change", update);
  }, []);

  return reduceMotion;
}

const reduceMotion = useReducedMotion();

return success && !reduceMotion ? (
  <Confetti recycle={false} aria-hidden="true" />
) : null;

React confetti FAQ

What is better-react-confetti?

better-react-confetti is a lightweight canvas-based React confetti component. It renders one wrapper and one canvas, then updates particle motion in a single animation loop.

Does this React confetti component support React 18 and React 19?

Yes. The package supports React 18.3 and the React 19 release line, with TypeScript declarations included.

Can I create a one-time confetti burst?

Yes. Set recycle to false so particles leave the stage without respawning. Remount the component when you want to trigger another burst.

Can I use custom confetti shapes?

The optimized canvas path supports the included Rectangle, Circle, and Triangle components. A DOM-based library is a better fit when every particle must render arbitrary React, SVG, or HTML content.

Add a focused celebration to your React app.

Install better-react-confetti from npm, or explore another small React package built around a narrow, practical job.