Vue Confetti Component
vue-confetti is a versatile Vue component and plugin designed for generating dynamic confetti effects within web applications. It allows developers to programmatically trigger, stop, and customize confetti showers through a `$confetti` instance injected into Vue components. The library supports various particle shapes including circles, rectangles, hearts, and custom images, along with extensive customization for colors, sizes, drop rates, and wind effects. Currently at version 2.3.0, it offers compatibility with both Vue 2 and Vue 3, with Vue 3 support introduced in February 2022. While releases are not frequent, they typically address bug fixes or add minor features, responding to ecosystem changes like Vue 3 adoption. Its primary advantage lies in providing a declarative and easily configurable solution for celebratory UI effects without direct canvas API manipulation, simplifying the process for adding dynamic visual flair.
Common errors
-
ReferenceError: window is not defined
cause Attempting to use `vue-confetti` in a server-side rendering (SSR) environment without marking it as client-only.fixEnsure `vue-confetti` is loaded only on the client. In Nuxt, configure it in `nuxt.config.js` as `{ src: '~/plugins/vue-confetti.js', mode: 'client' }`. -
Property '$confetti' does not exist on type 'ComponentPublicInstance<...>' or similar TypeScript error.
cause TypeScript does not automatically know about globally injected properties like `$confetti` unless explicitly declared.fixExtend Vue's `ComponentCustomProperties` interface via declaration merging. Create a `shims-vue-confetti.d.ts` file: ```typescript import 'vue'; declare module 'vue' { interface ComponentCustomProperties { $confetti: { start: (options?: any) => void; stop: () => void; update: (options?: any) => void; }; } } ``` Alternatively, cast `this` to `any` in component methods: `(this as any).$confetti.start()`. -
SyntaxError: Cannot use import statement outside a module
cause Attempting to use ESM `import` syntax in a CommonJS-only environment (e.g., older Node.js or specific build configurations), or vice-versa with `require()` in an ESM module.fixEnsure your project is configured for ESM (e.g., `"type": "module"` in `package.json` for Node.js) or use a bundler like Webpack/Vite that transpiles ESM to CJS if targeting older environments. For `vue-confetti`, stick to `import` statements as it's designed for modern module systems.
Warnings
- gotcha vue-confetti relies on browser globals (like `window`) and is not designed for server-side rendering (SSR). It will cause errors if rendered on the server without proper client-only configuration.
- gotcha The method of registering Vue plugins changed significantly between Vue 2 and Vue 3. Using `Vue.use()` for a Vue 3 application or `app.use()` for a Vue 2 application will result in errors.
- gotcha Calling `$confetti.update()` only configures the confetti properties; it does not automatically start the confetti animation. Developers often expect `update` to also trigger the effect.
Install
-
npm install vue-confetti -
yarn add vue-confetti -
pnpm add vue-confetti
Imports
- VueConfetti
import { VueConfetti } from 'vue-confetti';import VueConfetti from 'vue-confetti';
- Vue.use() (Vue 2)
Vue.use(VueConfetti); // Missing 'import Vue from "vue"'
import Vue from 'vue'; import VueConfetti from 'vue-confetti'; Vue.use(VueConfetti);
- app.use() (Vue 3)
Vue.use(VueConfetti); // For Vue 3, use `app.use()` on the app instance.
import { createApp } from 'vue'; import VueConfetti from 'vue-confetti'; const app = createApp(App); app.use(VueConfetti);
Quickstart
// main.ts or main.js
import { createApp } from 'vue';
import App from './App.vue';
import VueConfetti from 'vue-confetti';
const app = createApp(App);
app.use(VueConfetti);
app.mount('#app');
// App.vue
<template>
<main>
<h1>Confetti Time!</h1>
<button @click="start">Start Confetti</button>
<button @click="stop">Stop Confetti</button>
<button @click="love">Show Some Love (Hearts & Circles)</button>
<p>Click the buttons to trigger confetti effects.</p>
</main>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
methods: {
start(): void {
// Basic confetti with default settings
(this as any).$confetti.start();
},
stop(): void {
(this as any).$confetti.stop();
},
love(): void {
// Custom confetti with hearts and circles, then start and stop after 3s
(this as any).$confetti.update({
particles: [
{ type: 'heart', size: 12 },
{ type: 'circle', size: 8 }
],
defaultColors: [
'red', 'pink', '#FF69B4', '#E0BBE4', '#957DAD'
],
particlesPerFrame: 5
});
(this as any).$confetti.start(); // Must call start() after update()
setTimeout(() => (this as any).$confetti.stop(), 3000);
}
}
});
</script>
<style>
main {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
button {
margin: 0 10px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
</style>