Skip to content

Commit 2cca59e

Browse files
committed
feat: add PUConfetti component with canvas-based particle animation
1 parent b652e22 commit 2cca59e

File tree

3 files changed

+496
-0
lines changed

3 files changed

+496
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<template>
2+
<div class="confetti-demo">
3+
<CodeBlock
4+
v-if="type === 'basic'"
5+
:compare="false"
6+
>
7+
<template #preview>
8+
<div class="relative">
9+
<PUButton @click="triggerConfetti">
10+
Trigger Confetti
11+
</PUButton>
12+
<PUConfetti
13+
:active="isActive"
14+
:width="400"
15+
:height="200"
16+
class="absolute inset-0 pointer-events-none"
17+
/>
18+
</div>
19+
</template>
20+
<template #code>
21+
<slot name="code" />
22+
</template>
23+
</CodeBlock>
24+
25+
<CodeBlock
26+
v-if="type === 'custom-colors'"
27+
:compare="false"
28+
>
29+
<template #preview>
30+
<div class="relative">
31+
<PUButton @click="triggerCustomConfetti">
32+
Custom Colors
33+
</PUButton>
34+
<PUConfetti
35+
:active="isActive2"
36+
:colors="customColors"
37+
:particle-count="80"
38+
:width="400"
39+
:height="200"
40+
class="absolute inset-0 pointer-events-none"
41+
/>
42+
</div>
43+
</template>
44+
<template #code>
45+
<slot name="code" />
46+
</template>
47+
</CodeBlock>
48+
49+
<CodeBlock
50+
v-if="type === 'long-duration'"
51+
:compare="false"
52+
>
53+
<template #preview>
54+
<div class="relative">
55+
<PUButton @click="triggerLongConfetti">
56+
Long Duration
57+
</PUButton>
58+
<PUConfetti
59+
:active="isActive3"
60+
:duration="5000"
61+
:particle-count="100"
62+
:width="400"
63+
:height="200"
64+
class="absolute inset-0 pointer-events-none"
65+
/>
66+
</div>
67+
</template>
68+
<template #code>
69+
<slot name="code" />
70+
</template>
71+
</CodeBlock>
72+
</div>
73+
</template>
74+
75+
<script lang="ts" setup>
76+
import { ref } from 'vue'
77+
78+
defineProps<{
79+
type: 'basic' | 'custom-colors' | 'long-duration'
80+
}>()
81+
82+
const isActive = ref(false)
83+
const isActive2 = ref(false)
84+
const isActive3 = ref(false)
85+
86+
const customColors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#FF8C42', '#8B5CF6']
87+
88+
const triggerConfetti = () => {
89+
isActive.value = true
90+
setTimeout(() => {
91+
isActive.value = false
92+
}, 100)
93+
}
94+
95+
const triggerCustomConfetti = () => {
96+
isActive2.value = true
97+
setTimeout(() => {
98+
isActive2.value = false
99+
}, 100)
100+
}
101+
102+
const triggerLongConfetti = () => {
103+
isActive3.value = true
104+
setTimeout(() => {
105+
isActive3.value = false
106+
}, 100)
107+
}
108+
</script>
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
::doc-topic
2+
#title
3+
PUConfetti Component
4+
#description
5+
A hand-drawn style confetti animation component with customizable particles and physics
6+
::
7+
8+
::doc-topic
9+
#title
10+
Usage
11+
#description
12+
Basic Usage
13+
::
14+
::paper-show-confetti{type="basic"}
15+
#code
16+
```html
17+
<template>
18+
<div class="relative">
19+
<PUButton @click="triggerConfetti">
20+
Trigger Confetti
21+
</PUButton>
22+
<PUConfetti
23+
:active="isActive"
24+
:width="400"
25+
:height="200"
26+
class="absolute inset-0 pointer-events-none"
27+
/>
28+
</div>
29+
</template>
30+
31+
<script setup>
32+
const isActive = ref(false)
33+
34+
const triggerConfetti = () => {
35+
isActive.value = true
36+
setTimeout(() => {
37+
isActive.value = false
38+
}, 100)
39+
}
40+
</script>
41+
```
42+
::
43+
44+
::doc-topic
45+
#description
46+
Custom Colors
47+
::
48+
::paper-show-confetti{type="custom-colors"}
49+
#code
50+
```html
51+
<template>
52+
<PUConfetti
53+
:active="isActive"
54+
:colors="customColors"
55+
:particle-count="80"
56+
:width="400"
57+
:height="200"
58+
/>
59+
</template>
60+
61+
<script setup>
62+
const customColors = [
63+
'#FF6B6B', '#4ECDC4', '#45B7D1',
64+
'#96CEB4', '#FFEAA7', '#DDA0DD'
65+
]
66+
</script>
67+
```
68+
::
69+
70+
::doc-topic
71+
#description
72+
Long Duration
73+
::
74+
::paper-show-confetti{type="long-duration"}
75+
#code
76+
```html
77+
<template>
78+
<PUConfetti
79+
:active="isActive"
80+
:duration="5000"
81+
:particle-count="100"
82+
:width="400"
83+
:height="200"
84+
/>
85+
</template>
86+
```
87+
::
88+
89+
::doc-topic
90+
#title
91+
Props
92+
::
93+
::doc-table
94+
---
95+
headers: ['Prop', 'Type', 'Required', 'Default', 'Description']
96+
rows:
97+
- - 'active'
98+
- 'boolean'
99+
- 'No'
100+
- 'false'
101+
- 'Trigger confetti animation'
102+
- - 'colors'
103+
- 'string[]'
104+
- 'No'
105+
- 'Default color palette'
106+
- 'Array of colors for particles'
107+
- - 'particleCount'
108+
- 'number'
109+
- 'No'
110+
- '50'
111+
- 'Number of confetti particles'
112+
- - 'duration'
113+
- 'number'
114+
- 'No'
115+
- '3000'
116+
- 'Animation duration in milliseconds'
117+
- - 'width'
118+
- 'number'
119+
- 'No'
120+
- '400'
121+
- 'Canvas width'
122+
- - 'height'
123+
- 'number'
124+
- 'No'
125+
- '300'
126+
- 'Canvas height'
127+
- - 'customClass'
128+
- 'string'
129+
- 'No'
130+
- "''"
131+
- 'Custom CSS classes'
132+
---
133+
::
134+
135+
::doc-topic
136+
#title
137+
Events
138+
::
139+
::doc-table
140+
---
141+
headers: ['Event', 'Payload', 'Description']
142+
rows:
143+
- - 'start'
144+
- '-'
145+
- 'Emitted when animation starts'
146+
- - 'end'
147+
- '-'
148+
- 'Emitted when animation ends'
149+
---
150+
::
151+
152+
::doc-topic
153+
#title
154+
Features
155+
#description
156+
- Canvas-based particle system with smooth animations
157+
- Multiple particle types: circles, squares, triangles
158+
- Physics simulation with gravity and rotation
159+
- Customizable colors and particle count
160+
- Configurable animation duration
161+
- Hand-drawn style visual effects
162+
- Responsive canvas sizing
163+
- Performance optimized with requestAnimationFrame
164+
::
165+
166+
::doc-topic
167+
#title
168+
Dependencies
169+
#description
170+
- Tailwind CSS for styling
171+
- Vue 3 Composition API
172+
- HTML5 Canvas API
173+
::

0 commit comments

Comments
 (0)