Skip to content

Commit 42f45da

Browse files
authored
Merge pull request #82 from Aadityahq/main
Add Flare Button by Aaditayhq
2 parents 0e01a76 + c227ce0 commit 42f45da

2 files changed

Lines changed: 322 additions & 0 deletions

File tree

contributions/Aadityahq/button.jsx

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
5+
export default function FlareButton({
6+
text = '✨ Flare Button',
7+
onClick,
8+
disabled = false,
9+
variant = 'primary'
10+
}) {
11+
const [isHovered, setIsHovered] = useState(false);
12+
const [isActive, setIsActive] = useState(false);
13+
const [showFlare, setShowFlare] = useState(false);
14+
15+
const handleClick = () => {
16+
if (!disabled) {
17+
setShowFlare(true);
18+
if (onClick) {
19+
onClick();
20+
}
21+
setTimeout(() => {
22+
setShowFlare(false);
23+
}, 1500);
24+
}
25+
};
26+
27+
// Variant configurations
28+
const variants = {
29+
primary: {
30+
gradient: 'from-indigo-500 via-purple-500 to-purple-600',
31+
hoverGradient: 'hover:from-indigo-600 hover:via-purple-600 hover:to-purple-700',
32+
flareColors: ['#667eea', '#764ba2', '#a855f7', '#c084fc', '#e9d5ff']
33+
},
34+
secondary: {
35+
gradient: 'from-pink-400 via-pink-500 to-red-500',
36+
hoverGradient: 'hover:from-pink-500 hover:via-pink-600 hover:to-red-600',
37+
flareColors: ['#f093fb', '#f5576c', '#ff6b9d', '#fda4af', '#fbcfe8']
38+
},
39+
gradient: {
40+
gradient: 'from-pink-400 via-yellow-300 to-yellow-400',
41+
hoverGradient: 'hover:from-pink-500 hover:via-yellow-400 hover:to-yellow-500',
42+
flareColors: ['#fa709a', '#fee140', '#fbbf24', '#fde047', '#fef3c7']
43+
}
44+
};
45+
46+
const currentVariant = variants[variant];
47+
48+
// Generate flare particles (shooting stars effect)
49+
const flareParticles = Array.from({ length: 12 }, (_, i) => {
50+
const angle = (i * 30) - 15;
51+
const distance = 80 + Math.random() * 120;
52+
const size = Math.random() * 8 + 4;
53+
54+
return {
55+
id: i,
56+
angle,
57+
distance,
58+
size,
59+
color: currentVariant.flareColors[i % currentVariant.flareColors.length],
60+
delay: Math.random() * 0.1,
61+
duration: 0.8 + Math.random() * 0.4
62+
};
63+
});
64+
65+
// Generate sparkles around button
66+
const sparkles = Array.from({ length: 8 }, (_, i) => {
67+
const angle = (i * 45);
68+
return {
69+
id: i,
70+
angle,
71+
color: currentVariant.flareColors[i % currentVariant.flareColors.length],
72+
delay: i * 0.05
73+
};
74+
});
75+
76+
return (
77+
<div className="relative inline-block">
78+
<button
79+
onClick={handleClick}
80+
onMouseEnter={() => !disabled && setIsHovered(true)}
81+
onMouseLeave={() => {
82+
setIsHovered(false);
83+
setIsActive(false);
84+
}}
85+
onMouseDown={() => !disabled && setIsActive(true)}
86+
onMouseUp={() => setIsActive(false)}
87+
disabled={disabled}
88+
className={`
89+
relative px-12 py-4 font-semibold text-white uppercase tracking-wider
90+
rounded-full border-none cursor-pointer overflow-visible
91+
transition-all duration-400 ease-out
92+
focus:outline-none focus:ring-4 focus:ring-purple-300
93+
bg-gradient-to-r ${currentVariant.gradient} ${currentVariant.hoverGradient}
94+
${isHovered && !disabled ? '-translate-y-1' : 'translate-y-0'}
95+
${isActive && !disabled ? 'scale-95' : isHovered && !disabled ? 'scale-105' : 'scale-100'}
96+
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
97+
`}
98+
style={{
99+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif'
100+
}}
101+
aria-label={text}
102+
tabIndex={0}
103+
>
104+
{/* Button Content */}
105+
<span className="relative z-10 flex items-center justify-center gap-3">
106+
<span
107+
className={`
108+
inline-block transition-transform duration-300
109+
${isHovered && !disabled ? '-translate-x-1' : 'translate-x-0'}
110+
`}
111+
>
112+
{text}
113+
</span>
114+
<span
115+
className={`
116+
inline-flex items-center justify-center transition-all duration-300
117+
${isHovered && !disabled ? 'opacity-100 translate-x-0' : 'opacity-0 -translate-x-2'}
118+
`}
119+
>
120+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
121+
<path
122+
d="M7.5 15L12.5 10L7.5 5"
123+
stroke="currentColor"
124+
strokeWidth="2"
125+
strokeLinecap="round"
126+
strokeLinejoin="round"
127+
/>
128+
</svg>
129+
</span>
130+
</span>
131+
132+
{/* Ripple Effect */}
133+
{isActive && !disabled && (
134+
<div
135+
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-0 h-0 rounded-full bg-white/50 pointer-events-none animate-ripple"
136+
/>
137+
)}
138+
</button>
139+
140+
{/* FLARE EFFECT - Shooting Particles */}
141+
{showFlare && (
142+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none">
143+
{flareParticles.map(particle => (
144+
<div
145+
key={particle.id}
146+
className="absolute animate-flare-shoot"
147+
style={{
148+
left: '0',
149+
top: '0',
150+
width: `${particle.size}px`,
151+
height: `${particle.size}px`,
152+
backgroundColor: particle.color,
153+
borderRadius: '50%',
154+
filter: `blur(${particle.size * 0.3}px)`,
155+
'--flare-angle': `${particle.angle}deg`,
156+
'--flare-distance': `${particle.distance}px`,
157+
animationDelay: `${particle.delay}s`,
158+
animationDuration: `${particle.duration}s`
159+
}}
160+
/>
161+
))}
162+
</div>
163+
)}
164+
165+
{/* FLARE EFFECT - Expanding Ring */}
166+
{showFlare && (
167+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none">
168+
<div className="animate-flare-ring"
169+
style={{
170+
border: `4px solid ${currentVariant.flareColors[0]}`,
171+
borderRadius: '50%',
172+
opacity: 0,
173+
filter: 'blur(2px)'
174+
}}
175+
/>
176+
</div>
177+
)}
178+
179+
{/* FLARE EFFECT - Sparkles */}
180+
{showFlare && (
181+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none">
182+
{sparkles.map(sparkle => (
183+
<div
184+
key={sparkle.id}
185+
className="absolute animate-sparkle"
186+
style={{
187+
left: '0',
188+
top: '0',
189+
width: '4px',
190+
height: '16px',
191+
backgroundColor: sparkle.color,
192+
borderRadius: '50%',
193+
filter: 'blur(1px)',
194+
'--sparkle-angle': `${sparkle.angle}deg`,
195+
animationDelay: `${sparkle.delay}s`
196+
}}
197+
/>
198+
))}
199+
</div>
200+
)}
201+
202+
{/* FLARE EFFECT - Center Burst */}
203+
{showFlare && (
204+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none">
205+
<div
206+
className="animate-burst"
207+
style={{
208+
width: '30px',
209+
height: '30px',
210+
background: `radial-gradient(circle, ${currentVariant.flareColors[0]}, ${currentVariant.flareColors[2]}, transparent)`,
211+
borderRadius: '50%',
212+
filter: 'blur(6px)'
213+
}}
214+
/>
215+
</div>
216+
)}
217+
218+
<style jsx>{`
219+
@keyframes ripple {
220+
0% {
221+
width: 0;
222+
height: 0;
223+
opacity: 0.5;
224+
}
225+
100% {
226+
width: 200px;
227+
height: 200px;
228+
opacity: 0;
229+
}
230+
}
231+
232+
@keyframes flare-shoot {
233+
0% {
234+
transform: rotate(var(--flare-angle)) translateX(0) scale(1);
235+
opacity: 1;
236+
}
237+
70% {
238+
opacity: 1;
239+
}
240+
100% {
241+
transform: rotate(var(--flare-angle)) translateX(var(--flare-distance)) scale(0.3);
242+
opacity: 0;
243+
}
244+
}
245+
246+
@keyframes flare-ring {
247+
0% {
248+
width: 0;
249+
height: 0;
250+
opacity: 1;
251+
}
252+
100% {
253+
width: 300px;
254+
height: 300px;
255+
opacity: 0;
256+
}
257+
}
258+
259+
@keyframes sparkle {
260+
0% {
261+
transform: rotate(var(--sparkle-angle)) translateX(0) scale(1);
262+
opacity: 1;
263+
}
264+
50% {
265+
transform: rotate(var(--sparkle-angle)) translateX(60px) scale(1.5);
266+
opacity: 0.8;
267+
}
268+
100% {
269+
transform: rotate(var(--sparkle-angle)) translateX(100px) scale(0);
270+
opacity: 0;
271+
}
272+
}
273+
274+
@keyframes burst {
275+
0% {
276+
transform: scale(1);
277+
opacity: 1;
278+
}
279+
50% {
280+
transform: scale(4);
281+
opacity: 0.8;
282+
}
283+
100% {
284+
transform: scale(6);
285+
opacity: 0;
286+
}
287+
}
288+
289+
.animate-ripple {
290+
animation: ripple 0.6s ease-out forwards;
291+
}
292+
293+
.animate-flare-shoot {
294+
animation: flare-shoot 1s ease-out forwards;
295+
}
296+
297+
.animate-flare-ring {
298+
animation: flare-ring 1s ease-out forwards;
299+
}
300+
301+
.animate-sparkle {
302+
animation: sparkle 0.8s ease-out forwards;
303+
}
304+
305+
.animate-burst {
306+
animation: burst 0.6s ease-out forwards;
307+
}
308+
`}</style>
309+
</div>
310+
);
311+
}

contributions/Aadityahq/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const buttonMetadata = {
2+
name: "Flare Button",
3+
author: "Aadityahq",
4+
description: "A stunning gradient button with animated particles, glow effects, shine animation, and smooth interactions. Features multiple color variants and professional design suitable for modern web applications.",
5+
type: "react",
6+
tags: ["gradient", "animated", "particles", "glow", "interactive", "glassmorphism", "professional", "tailwind"],
7+
difficulty: "intermediate",
8+
preview: "Professional animated button with gradient backgrounds, floating particles, glow effects, and smooth hover animations"
9+
};
10+
11+
export default buttonMetadata;

0 commit comments

Comments
 (0)