Search

Search the site

All components

Confetti

Canvas-based confetti cannon with imperative `fire()` API and a boolean `trigger` prop. Bursts layer naturally because each particle fades on its own timeline.

Default
Fire a burst either imperatively via the `fire()` ref method or by toggling the `trigger` prop.

Confetti

1"use client";
2
3import { useRef, useState } from "react";
4import { Button } from "@/components/ui/button";
5import { Confetti, type ConfettiHandle, PropsVisualiser } from "@/registry/ui";
6
7type ConfettiExampleProps = {
8 particleCount: number;
9 spread: number;
10 duration: number;
11 gravity: number;
12 initialVelocity: number;
13}
14
15export function ConfettiDefaultExample() {
16 const ref = useRef<ConfettiHandle>(null);
17 const [trigger, setTrigger] = useState(false);
18 return (
19 <PropsVisualiser
20 title="Confetti"
21 schema={[
22 {
23 key: "particleCount",
24 type: "number",
25 min: 20,
26 max: 300,
27 step: 10,
28 defaultValue: 100,
29 },
30 {
31 key: "spread",
32 type: "number",
33 min: 10,
34 max: 180,
35 step: 5,
36 defaultValue: 70,
37 },
38 {
39 key: "duration",
40 type: "number",
41 min: 500,
42 max: 6000,
43 step: 100,
44 defaultValue: 2800,
45 },
46 {
47 key: "gravity",
48 type: "number",
49 min: 0.05,
50 max: 1,
51 step: 0.05,
52 defaultValue: 0.35,
53 },
54 {
55 key: "initialVelocity",
56 type: "number",
57 min: 5,
58 max: 50,
59 step: 1,
60 defaultValue: 22,
61 },
62 ]}
63 render={(props: ConfettiExampleProps) => (
64 <div className="flex flex-wrap items-center justify-center gap-3 p-8">
65 <Button onClick={() => ref.current?.fire()}>Fire (ref)</Button>
66 <Button variant="outline" onClick={() => setTrigger((t) => !t)}>
67 Fire (trigger)
68 </Button>
69 <Confetti ref={ref} trigger={trigger} {...props} />
70 </div>
71 )}
72 />
73 );
74}

Installation & source

Install via the shadcn CLI or copy the registry files manually.

bash
npx shadcn@latest add @tt-ui/confetti

Props

NameTypeDefaultDescription
triggerbooleanundefinedBoolean trigger - fires a burst on every false→true transition.
particleCountnumber100Number of particles per burst.
spreadnumber70Half-angle of the explosion cone in degrees.
durationnumber2800How long each particle lives in milliseconds.
colorsstring[]10-colour default paletteParticle colours.
origin{ x: number; y: number }{ x: 0.5, y: 1 }Launch origin as 0–1 fractions of the viewport (0,0 = top-left).
gravitynumber0.35Gravity acceleration in px/frame².
initialVelocitynumber22Initial speed of particles in px/frame.