|
| 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 | +} |
0 commit comments