Skip to content

Commit 228224d

Browse files
authored
feat: Implement Animated Loading State #170 (#293)
1 parent 0c103c1 commit 228224d

2 files changed

Lines changed: 192 additions & 22 deletions

File tree

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
'use client';
2+
3+
import { useEffect, useRef } from 'react';
4+
import { gsap } from 'gsap';
5+
6+
export default function Waitlist() {
7+
const containerRef = useRef<HTMLDivElement>(null);
8+
9+
useEffect(() => {
10+
if (containerRef.current) {
11+
const ctx = gsap.context(() => {
12+
gsap.set('.fade-in', { opacity: 0, y: 50 });
13+
gsap.set('.card', { scale: 0.9, opacity: 0 });
14+
gsap.set('.store-btn', { scale: 0.8, opacity: 0 });
15+
gsap.set('.logo-dots', { scale: 0, opacity: 0 });
16+
17+
// Create main timeline
18+
const tl = gsap.timeline({ defaults: { ease: 'power3.out' } });
19+
20+
// Card entrance with bounce
21+
tl.to('.card', {
22+
scale: 1,
23+
opacity: 1,
24+
duration: 0.8,
25+
ease: 'back.out(1.7)',
26+
})
27+
28+
// Logo dots animation
29+
.to(
30+
'.logo-dots',
31+
{
32+
scale: 1,
33+
opacity: 1,
34+
duration: 0.4,
35+
stagger: 0.1,
36+
ease: 'back.out(2)',
37+
},
38+
'-=0.5'
39+
)
40+
41+
// Content elements with stagger
42+
.to(
43+
'.fade-in',
44+
{
45+
opacity: 1,
46+
y: 0,
47+
duration: 0.6,
48+
stagger: 0.12,
49+
ease: 'power2.out',
50+
},
51+
'-=0.3'
52+
)
53+
54+
// Store buttons with bounce effect
55+
.to(
56+
'.store-btn',
57+
{
58+
scale: 1,
59+
opacity: 1,
60+
duration: 0.5,
61+
stagger: 0.15,
62+
ease: 'back.out(1.7)',
63+
},
64+
'-=0.2'
65+
);
66+
67+
if (containerRef.current) {
68+
const interactiveElements =
69+
containerRef.current.querySelectorAll('.hover-element');
70+
interactiveElements.forEach(element => {
71+
element.addEventListener('mouseenter', () => {
72+
gsap.to(element, {
73+
scale: 1.05,
74+
duration: 0.3,
75+
ease: 'power2.out',
76+
boxShadow: '0 10px 25px rgba(0,0,0,0.15)',
77+
});
78+
});
79+
80+
element.addEventListener('mouseleave', () => {
81+
gsap.to(element, {
82+
scale: 1,
83+
duration: 0.3,
84+
ease: 'power2.out',
85+
boxShadow: '0 4px 6px rgba(0,0,0,0.1)',
86+
});
87+
});
88+
});
89+
}
90+
91+
// Add subtle floating animation to the card
92+
gsap.to('.card', {
93+
y: -5,
94+
duration: 2,
95+
repeat: -1,
96+
yoyo: true,
97+
ease: 'power1.inOut',
98+
});
99+
}, containerRef);
100+
101+
return () => ctx.revert();
102+
}
103+
}, []);
104+
105+
return (
106+
<section
107+
ref={containerRef}
108+
className='flex min-h-screen items-center justify-center px-4'
109+
>
110+
<div className='card w-full max-w-2xl rounded-lg bg-white/95 p-8 shadow-xl backdrop-blur-sm'>
111+
{/* Logo */}
112+
<div className='fade-in mb-6 flex items-center gap-2'>
113+
<div className='flex space-x-1'>
114+
<div className='logo-dots h-5 w-5 rounded-full bg-yellow-400'></div>
115+
<div className='logo-dots h-5 w-5 rounded-full bg-green-500'></div>
116+
<div className='logo-dots h-5 w-5 rounded-full bg-red-500'></div>
117+
</div>
118+
<span className='text-lg font-semibold text-gray-900'>Company</span>
119+
</div>
120+
121+
{/* Title */}
122+
<h1 className='fade-in mb-4 text-3xl font-extrabold text-gray-900 md:text-4xl'>
123+
You're on the Waitlist! 🎉
124+
</h1>
125+
<p className='fade-in mb-6 text-base leading-relaxed text-gray-700 md:text-lg'>
126+
Congratulations! You've secured a spot on the exclusive Waitlist for{' '}
127+
<span className='font-medium text-purple-600'>[Product Name]</span>.
128+
To deliver a seamless experience that meets our customers'
129+
expectations, we will send out invitations in stages.
130+
</p>
131+
132+
{/* Button */}
133+
<button className='fade-in hover-element mb-8 rounded-md bg-black px-6 py-3 font-semibold text-white shadow-lg transition-colors hover:bg-gray-800'>
134+
See announcement
135+
</button>
136+
137+
{/* Sub text */}
138+
<p className='fade-in mb-10 text-sm text-gray-500'>
139+
You're receiving this email because you signed up for the{' '}
140+
<span className='font-medium'>[Product Name]</span> waitlist. If this
141+
doesn't seem right, please feel free to disregard this message.
142+
</p>
143+
144+
{/* Footer */}
145+
<div className='fade-in text-sm text-gray-700'>
146+
<div className='mb-3 flex items-center gap-2'>
147+
<div className='flex space-x-1'>
148+
<div className='h-4 w-4 rounded-full bg-gray-600'></div>
149+
<div className='h-4 w-4 rounded-full bg-gray-400'></div>
150+
</div>
151+
<span className='font-semibold'>Company</span>
152+
</div>
153+
154+
<p className='mb-4 text-sm'>
155+
[Product Name] at the touch of a button! Download our app for:
156+
</p>
157+
158+
{/* Store buttons */}
159+
<div className='mb-10 flex flex-col gap-3 sm:flex-row'>
160+
<div className='store-btn hover-element flex cursor-pointer items-center gap-3 rounded-lg bg-black px-4 py-3 text-white shadow-lg transition-colors hover:bg-gray-800'>
161+
<svg className='h-8 w-8' viewBox='0 0 24 24' fill='currentColor'>
162+
<path d='M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z' />
163+
</svg>
164+
<div>
165+
<div className='text-xs'>Download on the</div>
166+
<div className='text-sm font-semibold'>Mac App Store</div>
167+
</div>
168+
</div>
169+
170+
<div className='store-btn hover-element flex cursor-pointer items-center gap-3 rounded-lg bg-black px-4 py-3 text-white shadow-lg transition-colors hover:bg-gray-800'>
171+
<svg className='h-8 w-8' viewBox='0 0 24 24' fill='currentColor'>
172+
<path d='M3,20.5V3.5C3,2.91 3.34,2.39 3.84,2.15L13.69,12L3.84,21.85C3.34,21.6 3,21.09 3,20.5M16.81,15.12L6.05,21.34L14.54,12.85L16.81,15.12M20.16,10.81C20.5,11.08 20.75,11.5 20.75,12C20.75,12.5 20.53,12.9 20.18,13.18L17.89,14.5L15.39,12L17.89,9.5L20.16,10.81M6.05,2.66L16.81,8.88L14.54,11.15L6.05,2.66Z' />
173+
</svg>
174+
<div>
175+
<div className='text-xs'>GET IT ON</div>
176+
<div className='text-sm font-semibold'>Google Play</div>
177+
</div>
178+
</div>
179+
</div>
180+
181+
<p className='fade-in text-xs text-gray-500'>
182+
Don't want any more emails from [Company Name]?{' '}
183+
<span className='hover-element cursor-pointer font-medium text-purple-600 underline hover:text-purple-800'>
184+
Unsubscribe
185+
</span>
186+
.
187+
</p>
188+
</div>
189+
</div>
190+
</section>
191+
);
192+
}

package-lock.json

Lines changed: 0 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)