How to Add Confetti Button Explosions to Next.js & React

7 min read
November 17, 2025
How to Add Confetti Button Explosions to Next.js & React

Ever wondered why apps like Duolingo, Slack, and countless SaaS products use confetti animations? It's not just for fun—confetti creates memorable micro-interactions that boost user engagement and celebrate key moments in your user's journey.

In this tutorial, I'll show you how to implement button-triggered confetti explosions in your Next.js or React app. This technique is perfect for "Buy Now" buttons, form submissions, or any action worth celebrating. The implementation is lightweight, customizable, and production-ready.

By the end of this guide, you'll have working code you can drop into your project today.

Why Add Confetti to Your App?

Confetti animations aren't just decorative—they serve real UX purposes:

  • Celebration Micro-Interactions: Reward users when they complete important actions (purchases, signups, achievements)
  • Increased Engagement: Fun animations create memorable experiences that users want to share
  • Brand Personality: Adds playfulness and humanizes your product
  • Visual Feedback: Instantly communicates success without requiring users to read text

Real-world example? Our directory platform ConfettiSaaS uses confetti animations to reinforce our brand identity and create memorable user experiences. Users remember us because of it.

Prerequisites

Before we dive in, make sure you have:

  • A Next.js 13+ or React 18+ project set up
  • Basic understanding of React hooks (useState, useEffect)
  • Node.js and npm/yarn installed

That's it! The library we'll use handles all the complex animation logic for you.

Button-Triggered Confetti Explosion

This implementation is perfect for action buttons like "Buy Now," "Submit," or "Complete Task." When users click, confetti explodes from the button before navigating to the next page.

Install the Package

First, install the react-dom-confetti library:

npm install react-dom-confetti
# or
yarn add react-dom-confetti

Create the BuyButton Component

Create a new file components/BuyButton.tsx (or .jsx for JavaScript projects).

Step 1: Set up imports and component structure

'use client'
 
import { useRouter } from 'next/navigation';
import React from 'react';
import Confetti from 'react-dom-confetti';
 
const BuyButton = ({ url }: { url: string }) => {
  const router = useRouter();
  const [isExploding, setIsExploding] = React.useState(false);

The 'use client' directive is required in Next.js 13+ for client-side interactivity. We track the confetti state with isExploding.

Step 2: Add the click handler logic

  const handleBuyClick = () => {
    setIsExploding(true);
    setTimeout(() => {
      setIsExploding(false);
      router.push(url);
    }, 600);
  };

When clicked, we trigger the confetti, wait 600ms for the animation, then navigate to the target URL.

Step 3: Create the button with confetti

  return (
    <div className="mb-4 mx-auto justify-end">
      <button 
        onClick={handleBuyClick} 
        className="w-full font-bold max-w-lg mx-auto py-4 bg-green-500 text-white p-2 text-xl rounded-md shadow-lg hover:bg-green-600 transition duration-300 block"
      >
        Buy Now!
        <div className="flex justify-center items-center">
          <Confetti
            active={isExploding}
            config={{
              angle: 90,
              spread: 360,
              startVelocity: 40,
              elementCount: 70,
              dragFriction: 0.12,
              duration: 3000,
              stagger: 3,
              width: "10px",
              height: "10px",
              colors: ["#a864fd", "#22c1c3", "#ffce42", "#ff4081", "#32cd32", "#ff4500", "#1e90ff", "#ff69b4"],
            }}
          />
        </div>
      </button>
    </div>
  );
};
 
export default BuyButton;

How It Works

Let's break down the key parts:

  1. 'use client' Directive: Required in Next.js 13+ App Router since we're using client-side interactivity
  2. State Management: isExploding tracks whether confetti should be active
  3. Click Handler: Sets confetti to active, waits 600ms, then navigates to the URL
  4. Confetti Component: Takes an active prop and a config object

Understanding the Configuration

The config object gives you fine control over the confetti behavior:

  • angle: Direction of confetti (90 = upward, 180 = downward)
  • spread: How wide the confetti disperses (360 = full circle)
  • startVelocity: Initial speed of confetti pieces (higher = faster)
  • elementCount: Number of confetti pieces (more = denser)
  • dragFriction: How quickly confetti slows down (0.1 = slower fall)
  • duration: How long confetti stays visible (milliseconds)
  • stagger: Delay between each piece launching
  • width/height: Size of individual confetti pieces
  • colors: Array of hex colors for confetti pieces

Using the Component

Import and use your new confetti button anywhere in your app:

import BuyButton from '@/components/BuyButton';
 
export default function PricingPage() {
  return (
    <div>
      <h1>Premium Plan</h1>
      <p>$99/month</p>
      <BuyButton url="/checkout" />
    </div>
  );
}

That's it! When users click "Buy Now," they'll see a celebratory confetti explosion before being redirected.

Customization Ideas

Match Your Brand Colors:

colors: ["#your-brand-primary", "#your-brand-secondary", "#accent-color"]

Subtle Animation (Professional Apps):

elementCount: 30,
startVelocity: 20,
colors: ["#e0e0e0", "#c0c0c0", "#a0a0a0"]

Intense Celebration (Gaming/Social):

elementCount: 150,
startVelocity: 60,
duration: 5000

Common Use Cases

Success Page After Signup

Here's a practical example: one-time confetti burst on a success page.

'use client'
 
import { useEffect, useState } from 'react';
import Confetti from 'react-dom-confetti';
 
export default function SuccessPage() {
  const [showConfetti, setShowConfetti] = useState(false);
 
  useEffect(() => {
    // Trigger confetti on mount
    setShowConfetti(true);
    // Reset after animation
    const timer = setTimeout(() => setShowConfetti(false), 3000);
    return () => clearTimeout(timer);
  }, []);
 
  return (
    <div className="flex flex-col items-center justify-center min-h-screen">
      <h1>Welcome aboard! 🎉</h1>
      <p>Your account has been created successfully.</p>
      <div className="flex justify-center">
        <Confetti
          active={showConfetti}
          config={{
            angle: 90,
            spread: 360,
            startVelocity: 40,
            elementCount: 100,
            dragFriction: 0.12,
            duration: 3000,
            stagger: 3,
            width: "10px",
            height: "10px",
            colors: ["#a864fd", "#22c1c3", "#ffce42", "#ff4081"],
          }}
        />
      </div>
    </div>
  );
}

Achievement Unlock

Trigger confetti when users unlock achievements:

<button 
  onClick={() => {
    setIsExploding(true);
    unlockAchievement('first-purchase');
  }}
  className="achievement-button"
>
  Claim Reward
  <Confetti active={isExploding} config={achievementConfig} />
</button>

Combine the visual celebration with your backend logic for immediate user feedback.

Troubleshooting Common Issues

Hydration Errors in Next.js

Problem: "Hydration failed because the initial UI does not match what was rendered on the server."

Solution: Always use 'use client' directive at the top of your component file.

Confetti Not Appearing

Problem: Confetti renders but isn't visible.

Solutions:

  1. Check z-index: Ensure confetti isn't hidden behind other elements
  2. Verify state: Console.log your isExploding state to confirm it's changing
  3. Check for CSS conflicts: Some CSS resets might affect the confetti container
// Debug state changes
const handleBuyClick = () => {
  console.log('Triggering confetti');
  setIsExploding(true);
  setTimeout(() => {
    setIsExploding(false);
    router.push(url);
  }, 600);
};

Button Confetti Positioning Issues

Problem: Confetti appears in wrong location.

Solution: Ensure the confetti div is positioned correctly relative to the button:

<button style={{ position: 'relative' }}>
  <div style={{ position: 'absolute', left: '50%', top: '50%' }}>
    <Confetti active={isExploding} config={config} />
  </div>
</button>

Timing Adjustments

Quick Success Feedback:

setTimeout(() => {
  router.push(url);
}, 400); // Faster navigation

Dramatic Celebration:

setTimeout(() => {
  router.push(url);
}, 2000); // Let confetti play longer

What's Next?

You now have a production-ready button confetti implementation that adds delight to user interactions. This technique works perfectly for:

  • Call-to-action buttons
  • Form submissions
  • Achievement unlocks
  • Purchase confirmations

Want more confetti effects? Stay tuned for more tutorials on adding continuous background confetti to your entire app—perfect for landing pages and branded experiences like we use on ConfettiSaaS.com.

Resources

Ready to make your app more fun? Drop this implementation into your project today and watch user engagement improve. And if you're building a SaaS product, don't forget to list it on ConfettiSaaS for visibility and backlinks!

Have questions about implementing button confetti? Found a creative use case? Let's chat on Twitter or in the comments below.

👨‍💻
Written by
Lars
Building ConfettiSaaS and helping SaaS founders grow.
Focus: SaaS growth, marketing, and SEO. Also, I love confetti.