Feedback feedbackanimation

Confetti Success

Feedback with falling confetti celebration.

Preview

Success!

Usage

Copy the full block below to use this component with its imports.

astro
---
import { ConfettiSuccess } from 'astro-component-kit';
---

<ConfettiFeedback label="Mission Accomplished" />
--- import { ConfettiSuccess } from 'astro-component-kit'; --- <ConfettiFeedback label="Mission Accomplished" />

Manual Installation

If you are not using the npm package, create a new file src/components/lib/ConfettiSuccess.astro and paste the following code:

astro
---
/**
 * ConfettiFeedback — A celebration component that triggers a falling confetti animation.
 * 
 * @param {string} label - Text to display briefly before/during confetti. Default is "Success!".
 * @param {string} color - Primary color of the confetti pieces. Default is 'var(--c-primary)'.
 * @param {boolean} active - If true, starts the animation immediately. Default is true.
 */
interface Props {
  label?: string;
  color?: string;
  active?: boolean;
}

const { label = "Success!", color = 'var(--c-primary, #6366f1)', active = true } = Astro.props;
---

<div class:list={["confetti-trigger", { "confetti-trigger--active": active }]}>
  <span class="confetti-label">{label}</span>
  <div class="confetti-container" aria-hidden="true" style={`--confetti-color: ${color}`}>
    {Array.from({ length: 12 }).map((_, i) => (
      <div 
        class="confetti-piece" 
        style={`--l: ${Math.random() * 100}%; --d: ${Math.random() * 2}s; --r: ${Math.random() * 360}deg; --s: ${0.5 + Math.random()} `}
      ></div>
    ))}
  </div>
</div>

<style>
  .confetti-trigger { 
    position: relative; 
    display: flex; 
    flex-direction: column; 
    align-items: center; 
    padding: var(--sp-4, 1rem);
    width: fit-content;
    overflow: hidden;
  }
  
  .confetti-label { 
    font-size: 1.25rem; 
    font-weight: 800; 
    color: var(--c-text-1, #fff); 
    z-index: 1; 
    text-shadow: 0 4px 10px rgba(0,0,0,0.3);
  }
  
  .confetti-container { 
    position: absolute; 
    inset: 0; 
    pointer-events: none; 
    opacity: 0; 
    transition: opacity 0.3s;
  }
  
  .confetti-trigger--active .confetti-container { opacity: 1; }
  
  .confetti-piece { 
    position: absolute; 
    left: var(--l); 
    top: -20px; 
    width: 10px; height: 10px; 
    background: var(--confetti-color); 
    border-radius: 2px; 
    transform: rotate(var(--r)) scale(var(--s));
    opacity: 0; 
  }
  
  .confetti-trigger--active .confetti-piece {
    animation: confetti-fall 2.5s linear infinite var(--d); 
  }
  
  @keyframes confetti-fall {
    0% { transform: translateY(0) rotate(0deg) scale(var(--s)); opacity: 1; }
    25% { transform: translateY(40px) rotate(90deg) translateX(10px); }
    50% { transform: translateY(80px) rotate(180deg) translateX(-10px); }
    75% { transform: translateY(120px) rotate(270deg) translateX(5px); }
    100% { transform: translateY(160px) rotate(360deg); opacity: 0; }
  }
</style>
--- /** * ConfettiFeedback — A celebration component that triggers a falling confetti animation. * * @param {string} label - Text to display briefly before/during confetti. Default is "Success!". * @param {string} color - Primary color of the confetti pieces. Default is 'var(--c-primary)'. * @param {boolean} active - If true, starts the animation immediately. Default is true. */ interface Props { label?: string; color?: string; active?: boolean; } const { label = "Success!", color = 'var(--c-primary, #6366f1)', active = true } = Astro.props; --- <div class:list={["confetti-trigger", { "confetti-trigger--active": active }]}> <span class="confetti-label">{label}</span> <div class="confetti-container" aria-hidden="true" style={`--confetti-color: ${color}`}> {Array.from({ length: 12 }).map((_, i) => ( <div class="confetti-piece" style={`--l: ${Math.random() * 100}%; --d: ${Math.random() * 2}s; --r: ${Math.random() * 360}deg; --s: ${0.5 + Math.random()} `} ></div> ))} </div> </div> <style> .confetti-trigger { position: relative; display: flex; flex-direction: column; align-items: center; padding: var(--sp-4, 1rem); width: fit-content; overflow: hidden; } .confetti-label { font-size: 1.25rem; font-weight: 800; color: var(--c-text-1, #fff); z-index: 1; text-shadow: 0 4px 10px rgba(0,0,0,0.3); } .confetti-container { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity 0.3s; } .confetti-trigger--active .confetti-container { opacity: 1; } .confetti-piece { position: absolute; left: var(--l); top: -20px; width: 10px; height: 10px; background: var(--confetti-color); border-radius: 2px; transform: rotate(var(--r)) scale(var(--s)); opacity: 0; } .confetti-trigger--active .confetti-piece { animation: confetti-fall 2.5s linear infinite var(--d); } @keyframes confetti-fall { 0% { transform: translateY(0) rotate(0deg) scale(var(--s)); opacity: 1; } 25% { transform: translateY(40px) rotate(90deg) translateX(10px); } 50% { transform: translateY(80px) rotate(180deg) translateX(-10px); } 75% { transform: translateY(120px) rotate(270deg) translateX(5px); } 100% { transform: translateY(160px) rotate(360deg); opacity: 0; } } </style>

Quick Info

Category
Feedback
Filename
ConfettiSuccess.astro
Dependencies
None — pure Astro + CSS
Tags
feedbackanimation