
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
react-congratulation
Advanced tools
React Congratulation - Celebration confetti effects for success, achievements, and special moments. Perfect for React apps needing success animations, party effects, and victory celebrations.
React Congratulation - Beautiful celebration confetti effects for React applications. Perfect for success messages, achievements, victories, and special moments.
🎉 Lightweight • 🚀 High Performance • 🎨 Customizable • 📦 Zero Dependencies
npm install react-congratulation
yarn add react-congratulation
pnpm add react-congratulation
Requirements: React >=16.8.0
See it in action: demo
Experience the celebration effects live in our Lucky Wheel application!
import Fireworks from "react-congratulation/dist/presets/fireworks";
function SuccessMessage() {
return <Fireworks autorun={{ speed: 3 }} />;
}
import { DynamicConfetti } from "react-congratulation";
function SuccessMessage() {
return <DynamicConfetti effect="fireworks" autorun={{ speed: 3 }} />;
}
import { useState } from "react";
import { DynamicConfetti } from "react-congratulation";
function AchievementButton() {
const [celebrate, setCelebrate] = useState(false);
return (
<>
<button onClick={() => setCelebrate(true)}>
Complete Achievement
</button>
{celebrate && (
<DynamicConfetti
effect="realistic"
autorun={{ speed: 3, duration: 3000 }}
/>
)}
</>
);
}
Perfect for celebrations and success moments
import Fireworks from "react-congratulation/dist/presets/fireworks";
<Fireworks autorun={{ speed: 3 }} />
Beautiful snow effect for winter themes
import Snow from "react-congratulation/dist/presets/snow";
<Snow autorun={{ speed: 1, duration: 5000 }} />
Most realistic confetti effect
import Realistic from "react-congratulation/dist/presets/realistic";
<Realistic autorun={{ speed: 3 }} />
Powerful burst effect
import Explosion from "react-congratulation/dist/presets/explosion";
<Explosion autorun={{ speed: 3 }} />
Confetti from multiple directions
import Crossfire from "react-congratulation/dist/presets/crossfire";
<Crossfire autorun={{ speed: 3 }} />
Rainbow celebration
import Pride from "react-congratulation/dist/presets/pride";
<Pride autorun={{ speed: 3 }} />
Spiral effect
import Vortex from "react-congratulation/dist/presets/vortex";
<Vortex autorun={{ speed: 3 }} />
Light particles effect
import Photons from "react-congratulation/dist/presets/photons";
<Photons autorun={{ speed: 3 }} />
| Prop | Type | Description |
|---|---|---|
width | string | number | Canvas width |
height | string | number | Canvas height |
className | string | CSS class name |
style | CSSProperties | Inline styles |
globalOptions | GlobalOptions | Global animation settings |
onInit | function | Callback when component mounts |
| Prop | Type | Description |
|---|---|---|
autorun | { speed: number; duration?: number; delay?: number } | Auto-start animation on mount |
decorateOptions | function | Customize animation options |
onInit | function | Access to confetti and conductor instances |
type TConductorInstance = {
run: (params: { speed: number; duration?: number; delay?: number }) => void;
shoot: () => void;
pause: () => void;
stop: () => void;
};
import { getAllEffects } from "react-congratulation";
const effects = getAllEffects();
// Returns: ["fireworks", "snow", "realistic", "explosion", "crossfire", "pride", "vortex", "photons"]
import { useState } from "react";
import { DynamicConfetti, getAllEffects, EffectName } from "react-congratulation";
function EffectSelector() {
const [selectedEffect, setSelectedEffect] = useState<EffectName>("fireworks");
const [show, setShow] = useState(false);
const effects = getAllEffects();
const handleCelebrate = () => {
setShow(true);
setTimeout(() => setShow(false), 3000);
};
return (
<div>
<select
value={selectedEffect}
onChange={(e) => setSelectedEffect(e.target.value as EffectName)}
>
{effects.map((effect) => (
<option key={effect} value={effect}>
{effect.charAt(0).toUpperCase() + effect.slice(1)}
</option>
))}
</select>
<button onClick={handleCelebrate}>Celebrate!</button>
{show && (
<DynamicConfetti
effect={selectedEffect}
autorun={{ speed: 3, duration: 3000 }}
/>
)}
</div>
);
}
import { useState } from "react";
import Realistic from "react-congratulation/dist/presets/realistic";
function ContactForm() {
const [success, setSuccess] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
// Submit form...
setSuccess(true);
setTimeout(() => setSuccess(false), 3000);
};
return (
<>
<form onSubmit={handleSubmit}>
{/* form fields */}
<button type="submit">Submit</button>
</form>
{success && <Realistic autorun={{ speed: 3 }} />}
</>
);
}
import Fireworks from "react-congratulation/dist/presets/fireworks";
function PaymentSuccess() {
return (
<div className="success-page">
<h1>Payment Successful!</h1>
<Fireworks autorun={{ speed: 3, duration: 5000 }} />
</div>
);
}
import Explosion from "react-congratulation/dist/presets/explosion";
function Achievement({ unlocked }) {
return unlocked ? (
<div className="achievement">
<h2>Achievement Unlocked! 🏆</h2>
<Explosion autorun={{ speed: 5 }} />
</div>
) : null;
}
import { useRef } from "react";
import Fireworks from "react-congratulation/dist/presets/fireworks";
function ManualControl() {
const conductorRef = useRef(null);
const handleInit = ({ conductor }) => {
conductorRef.current = conductor;
};
const celebrate = () => {
conductorRef.current?.shoot();
};
return (
<>
<button onClick={celebrate}>Celebrate!</button>
<Fireworks onInit={handleInit} />
</>
);
}
import ReactCongratulation from "react-congratulation";
import { useEffect, useRef } from "react";
function CustomAnimation() {
const confettiRef = useRef(null);
useEffect(() => {
const interval = setInterval(() => {
confettiRef.current?.({
particleCount: 100,
spread: 70,
origin: { y: 0.6 }
});
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<ReactCongratulation
onInit={({ confetti }) => {
confettiRef.current = confetti;
}}
/>
);
}
Store effect configuration in Redux and trigger celebrations from anywhere in your app.
// store/celebrationSlice.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { EffectName } from "react-congratulation";
interface CelebrationState {
effect: EffectName | null;
timestamp: number;
}
const initialState: CelebrationState = {
effect: null,
timestamp: 0,
};
const celebrationSlice = createSlice({
name: "celebration",
initialState,
reducers: {
triggerCelebration: (state, action: PayloadAction<EffectName>) => {
state.effect = action.payload;
state.timestamp = Date.now();
},
clearCelebration: (state) => {
state.effect = null;
},
},
});
export const { triggerCelebration, clearCelebration } =
celebrationSlice.actions;
export default celebrationSlice.reducer;
// components/CelebrationContainer.tsx
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { DynamicConfetti } from "react-congratulation";
import { clearCelebration } from "../store/celebrationSlice";
function CelebrationContainer() {
const dispatch = useDispatch();
const { effect, timestamp } = useSelector((state) => state.celebration);
useEffect(() => {
if (effect) {
const timer = setTimeout(() => {
dispatch(clearCelebration());
}, 3000);
return () => clearTimeout(timer);
}
}, [timestamp, effect, dispatch]);
if (!effect) return null;
return <DynamicConfetti effect={effect} autorun={{ speed: 3 }} />;
}
export default CelebrationContainer;
// Trigger from a saga
function* handleSuccessSaga() {
yield put(triggerCelebration("fireworks"));
}
// Trigger from a thunk
export const completeTask = createAsyncThunk(
"tasks/complete",
async (taskId, { dispatch }) => {
await api.completeTask(taskId);
dispatch(triggerCelebration("realistic"));
}
);
// Trigger from a component
function PaymentButton() {
const dispatch = useDispatch();
const handlePayment = async () => {
await processPayment();
dispatch(triggerCelebration("explosion"));
};
return <button onClick={handlePayment}>Pay Now</button>;
}
// contexts/CelebrationContext.tsx
import React, { createContext, useContext, useState, useCallback } from "react";
import { DynamicConfetti, EffectName } from "react-congratulation";
interface CelebrationContextType {
celebrate: (effect: EffectName) => void;
}
const CelebrationContext = createContext<CelebrationContextType | undefined>(
undefined
);
export function CelebrationProvider({ children }: { children: React.ReactNode }) {
const [effect, setEffect] = useState<EffectName | null>(null);
const celebrate = useCallback((effectName: EffectName) => {
setEffect(effectName);
setTimeout(() => setEffect(null), 3000);
}, []);
return (
<CelebrationContext.Provider value={{ celebrate }}>
{children}
{effect && <DynamicConfetti effect={effect} autorun={{ speed: 3 }} />}
</CelebrationContext.Provider>
);
}
export function useCelebration() {
const context = useContext(CelebrationContext);
if (!context) {
throw new Error("useCelebration must be used within CelebrationProvider");
}
return context;
}
// Usage in any component
function AnyComponent() {
const { celebrate } = useCelebration();
return <button onClick={() => celebrate("fireworks")}>Success!</button>;
}
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import { DynamicConfetti, EffectName, getAllEffects } from "react-congratulation";
function QueryCelebration() {
const [searchParams, setSearchParams] = useSearchParams();
const [show, setShow] = useState(false);
const effect = searchParams.get("celebration") as EffectName;
const validEffects = getAllEffects();
useEffect(() => {
if (effect && validEffects.includes(effect)) {
setShow(true);
setTimeout(() => {
setShow(false);
searchParams.delete("celebration");
setSearchParams(searchParams);
}, 3000);
}
}, [effect]);
if (!show || !effect) return null;
return <DynamicConfetti effect={effect} autorun={{ speed: 3 }} />;
}
// Usage: Navigate to /success?celebration=fireworks
import { useEffect, useState } from "react";
import { DynamicConfetti, EffectName } from "react-congratulation";
function RealtimeCelebration() {
const [effect, setEffect] = useState<EffectName | null>(null);
useEffect(() => {
const ws = new WebSocket("wss://your-server.com");
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === "celebration") {
setEffect(data.effect);
setTimeout(() => setEffect(null), 3000);
}
};
return () => ws.close();
}, []);
if (!effect) return null;
return <DynamicConfetti effect={effect} autorun={{ speed: 3 }} />;
}
import { useEffect, useState } from "react";
import { DynamicConfetti, EffectName, getAllEffects } from "react-congratulation";
function CelebrationWithPreferences() {
const [effect, setEffect] = useState<EffectName>("fireworks");
const [show, setShow] = useState(false);
// Load saved preference
useEffect(() => {
const saved = localStorage.getItem("preferredEffect") as EffectName;
if (saved && getAllEffects().includes(saved)) {
setEffect(saved);
}
}, []);
const handleEffectChange = (newEffect: EffectName) => {
setEffect(newEffect);
localStorage.setItem("preferredEffect", newEffect);
};
const celebrate = () => {
setShow(true);
setTimeout(() => setShow(false), 3000);
};
return (
<div>
<select
value={effect}
onChange={(e) => handleEffectChange(e.target.value as EffectName)}
>
{getAllEffects().map((e) => (
<option key={e} value={e}>
{e}
</option>
))}
</select>
<button onClick={celebrate}>Celebrate</button>
{show && <DynamicConfetti effect={effect} autorun={{ speed: 3 }} />}
</div>
);
}
This library is perfect when searching for:
import Fireworks from "react-congratulation/dist/presets/fireworks";
function CustomFireworks() {
const decorateOptions = (options) => ({
...options,
colors: ['#ff0000', '#00ff00', '#0000ff'],
particleCount: 200,
});
return (
<Fireworks
autorun={{ speed: 3 }}
decorateOptions={decorateOptions}
/>
);
}
import Realistic from "react-congratulation/dist/presets/realistic";
function StyledConfetti() {
return (
<Realistic
autorun={{ speed: 3 }}
style={{
position: 'absolute',
width: '100%',
height: '100%',
zIndex: 999,
}}
/>
);
}
MIT © Code4Change
Built with the amazing canvas-confetti library.
Special Thanks to Luck4You for open-sourcing this library and sharing it with everyone!
We believe in open source and sharing knowledge with the community. This library is free to use and we encourage everyone to contribute and improve it together.
Need help or want to collaborate? Feel free to reach out via Telegram!
react congratulation, react congratulations, react confetti, react celebration, react success animation, react party effect, react achievement, react victory animation, canvas confetti react, react fireworks, celebration component, success effect, achievement animation, party animation react, react canvas animation, confetti library, celebration library, success notification, achievement effect, victory celebration, react animation library, canvas animation react, confetti effect, celebration effect, party component
FAQs
React Congratulation - Celebration confetti effects for success, achievements, and special moments. Perfect for React apps needing success animations, party effects, and victory celebrations.
We found that react-congratulation demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.