Skip to content

Commit d32d8cf

Browse files
feat(hero): add animated DiscordButton with GSAP magnetic 3D tilt and Framer Motion floating aura, add improvement issue template
1 parent 0edb559 commit d32d8cf

3 files changed

Lines changed: 187 additions & 39 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Improvement / Feature Request
2+
description: Suggest an idea, enhancement, or new feature for CommitPulse
3+
title: 'Enhancement: '
4+
labels: ['enhancement']
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Thank you for suggesting an improvement! Please fill out this form to help us understand your idea.
10+
11+
💡 **Pro-Tip:** If you'd like to build this yourself, just comment `/claim` after submitting!
12+
13+
- type: textarea
14+
id: overview
15+
attributes:
16+
label: Overview
17+
description: A clear and concise description of the enhancement or feature you are proposing.
18+
validations:
19+
required: true
20+
21+
- type: textarea
22+
id: proposed_changes
23+
attributes:
24+
label: Proposed Changes
25+
description: How should this feature work? What exactly needs to be changed or added?
26+
value: |
27+
1.
28+
2.
29+
3.
30+
validations:
31+
required: true
32+
33+
- type: textarea
34+
id: expected_outcome
35+
attributes:
36+
label: Expected Outcome
37+
description: How will this improvement benefit the users or the project?
38+
validations:
39+
required: true
40+
41+
- type: textarea
42+
id: screenshots
43+
attributes:
44+
label: Visual Previews / Design Inspiration
45+
description: (Optional) Drop any mockups, screenshots, or inspiration links here.
46+
validations:
47+
required: false

app/page.tsx

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { useDebounce } from '@/hooks/useDebounce';
1313
import { Footer } from '@/app/components/Footer';
1414
import InteractiveViewer from '@/components/InteractiveViewer';
1515
import { FeatureCard, FeatureCardsSection } from '@/components/FeatureCards';
16+
import { DiscordButton } from '@/components/DiscordButton';
1617

1718
const Icons = {
1819
Github: () => (
@@ -148,45 +149,7 @@ export default function LandingPage() {
148149

149150
<main className="relative z-10 mx-auto max-w-6xl px-6 mt-32">
150151
<div className="mb-16 text-center">
151-
<motion.a
152-
href="https://discord.gg/Cb73bS79j"
153-
target="_blank"
154-
rel="noopener noreferrer"
155-
initial={{ opacity: 0, y: -10 }}
156-
animate={{ opacity: 1, y: 0 }}
157-
transition={{ duration: 0.5, delay: 0.1 }}
158-
whileHover={{ scale: 1.04 }}
159-
whileTap={{ scale: 0.97 }}
160-
className="mb-8 inline-flex items-center gap-2.5 rounded-full border border-black/10 bg-white px-4 py-1.5 text-xs font-medium text-gray-700 shadow-sm backdrop-blur-sm transition-colors duration-200 hover:bg-black/[0.03] hover:border-black/20 hover:text-black dark:border-white/10 dark:bg-white/[0.04] dark:text-white/50 dark:hover:bg-white/[0.07] dark:hover:border-white/20 dark:hover:text-white/80"
161-
>
162-
<span className="relative flex h-1.5 w-1.5">
163-
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-black/40 dark:bg-white/50" />
164-
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-black/70 dark:bg-white/70" />
165-
</span>
166-
<svg
167-
width="13"
168-
height="13"
169-
viewBox="0 0 24 24"
170-
fill="currentColor"
171-
className="opacity-60"
172-
>
173-
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3333-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3333-.946 2.4189-2.1568 2.4189Z" />
174-
</svg>
175-
Join the community on Discord
176-
<svg
177-
width="10"
178-
height="10"
179-
viewBox="0 0 24 24"
180-
fill="none"
181-
stroke="currentColor"
182-
strokeWidth="2.5"
183-
strokeLinecap="round"
184-
strokeLinejoin="round"
185-
className="opacity-40"
186-
>
187-
<path d="M7 17L17 7M17 7H7M17 7v10" />
188-
</svg>
189-
</motion.a>
152+
<DiscordButton />
190153

191154
<motion.div
192155
initial={{ opacity: 0, y: 20 }}

components/DiscordButton.tsx

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
'use client';
2+
3+
import { useRef, useState, useEffect } from 'react';
4+
import { motion, useAnimation } from 'framer-motion';
5+
import gsap from 'gsap';
6+
7+
export function DiscordButton() {
8+
const buttonRef = useRef<HTMLAnchorElement>(null);
9+
const [isHovered, setIsHovered] = useState(false);
10+
11+
// Magnetic hover effect using GSAP for smooth mouse tracking
12+
useEffect(() => {
13+
const button = buttonRef.current;
14+
if (!button) return;
15+
16+
const handleMouseMove = (e: MouseEvent) => {
17+
if (!isHovered) return;
18+
const rect = button.getBoundingClientRect();
19+
const x = e.clientX - rect.left - rect.width / 2;
20+
const y = e.clientY - rect.top - rect.height / 2;
21+
22+
gsap.to(button, {
23+
x: x * 0.2, // move 20% towards the mouse
24+
y: y * 0.2,
25+
rotationX: -y * 0.1,
26+
rotationY: x * 0.1,
27+
duration: 0.4,
28+
ease: 'power2.out',
29+
transformPerspective: 500,
30+
});
31+
};
32+
33+
const handleMouseLeave = () => {
34+
setIsHovered(false);
35+
gsap.to(button, {
36+
x: 0,
37+
y: 0,
38+
rotationX: 0,
39+
rotationY: 0,
40+
duration: 0.7,
41+
ease: 'elastic.out(1, 0.3)',
42+
});
43+
};
44+
45+
button.addEventListener('mousemove', handleMouseMove);
46+
button.addEventListener('mouseleave', handleMouseLeave);
47+
48+
return () => {
49+
button.removeEventListener('mousemove', handleMouseMove);
50+
button.removeEventListener('mouseleave', handleMouseLeave);
51+
};
52+
}, [isHovered]);
53+
54+
return (
55+
<div className="relative inline-block perspective-1000">
56+
{/* Background Glow */}
57+
<motion.div
58+
className="absolute -inset-1 rounded-full opacity-30 blur-md bg-gradient-to-r from-[#5865F2]/50 via-purple-500/50 to-[#5865F2]/50 pointer-events-none"
59+
animate={{
60+
scale: isHovered ? 1.2 : 1,
61+
opacity: isHovered ? 0.8 : 0.4,
62+
rotate: isHovered ? 180 : 0,
63+
}}
64+
transition={{
65+
duration: isHovered ? 0.4 : 3,
66+
rotate: {
67+
duration: 8,
68+
repeat: Infinity,
69+
ease: 'linear',
70+
},
71+
}}
72+
/>
73+
74+
<motion.div
75+
animate={{ y: [0, -8, 0] }}
76+
transition={{ duration: 3, repeat: Infinity, ease: 'easeInOut' }}
77+
className="relative z-10"
78+
>
79+
<motion.a
80+
ref={buttonRef}
81+
href="https://discord.gg/Cb73bS79j"
82+
target="_blank"
83+
rel="noopener noreferrer"
84+
onMouseEnter={() => setIsHovered(true)}
85+
initial={{ opacity: 0, y: -20, scale: 0.9 }}
86+
animate={{ opacity: 1, y: 0, scale: 1 }}
87+
transition={{
88+
type: 'spring',
89+
stiffness: 260,
90+
damping: 20,
91+
delay: 0.1,
92+
}}
93+
whileTap={{ scale: 0.95 }}
94+
className="relative mb-8 inline-flex items-center gap-3 rounded-full border border-black/10 bg-white/80 backdrop-blur-md px-5 py-2 text-sm font-semibold text-gray-700 shadow-[0_8px_30px_rgb(0,0,0,0.08)] transition-all hover:text-black dark:border-white/10 dark:bg-[#0a0a0a]/80 dark:text-white/80 dark:hover:text-white overflow-hidden group"
95+
style={{ transformStyle: 'preserve-3d' }}
96+
>
97+
{/* Animated Sweep effect on hover */}
98+
<div className="absolute inset-0 translate-y-[100%] bg-gradient-to-r from-[#5865F2]/10 via-[#5865F2]/20 to-[#5865F2]/10 transition-transform duration-500 ease-out group-hover:translate-y-0" />
99+
100+
{/* Pulsing Dot */}
101+
<span className="relative flex h-2 w-2 z-10">
102+
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#5865F2] opacity-75" />
103+
<span className="relative inline-flex h-2 w-2 rounded-full bg-[#5865F2] shadow-[0_0_8px_#5865F2]" />
104+
</span>
105+
106+
{/* Discord Icon */}
107+
<svg
108+
width="16"
109+
height="16"
110+
viewBox="0 0 24 24"
111+
fill="currentColor"
112+
className="z-10 text-[#5865F2] transition-transform duration-300 group-hover:scale-110 group-hover:rotate-[-5deg]"
113+
>
114+
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3333-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3333-.946 2.4189-2.1568 2.4189Z" />
115+
</svg>
116+
117+
<span className="z-10 bg-gradient-to-br from-gray-900 to-gray-500 bg-clip-text text-transparent dark:from-white dark:to-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors duration-300">
118+
Join the community on Discord
119+
</span>
120+
121+
<svg
122+
width="14"
123+
height="14"
124+
viewBox="0 0 24 24"
125+
fill="none"
126+
stroke="currentColor"
127+
strokeWidth="2.5"
128+
strokeLinecap="round"
129+
strokeLinejoin="round"
130+
className="z-10 opacity-40 transition-all duration-300 group-hover:opacity-100 group-hover:translate-x-1 group-hover:-translate-y-1 group-hover:text-[#5865F2]"
131+
>
132+
<path d="M7 17L17 7M17 7H7M17 7v10" />
133+
</svg>
134+
</motion.a>
135+
</motion.div>
136+
</div>
137+
);
138+
}

0 commit comments

Comments
 (0)