diff --git a/apps/website/src/components/shared/AnnouncementToast.tsx b/apps/website/src/components/shared/AnnouncementToast.tsx index 999a8ff23..a4f559023 100644 --- a/apps/website/src/components/shared/AnnouncementToast.tsx +++ b/apps/website/src/components/shared/AnnouncementToast.tsx @@ -11,18 +11,20 @@ const ANNOUNCEMENT_DATE = '2026-04-07'; const STORAGE_KEY = `dismissed-announcement-${ANNOUNCEMENT_DATE}`; const DELAY_MS = 30_000; +type Step = 'cta' | 'form' | 'sent'; + export function AnnouncementToast() { const [visible, setVisible] = useState(false); + const [step, setStep] = useState('cta'); + const [email, setEmail] = useState(''); + const [submitting, setSubmitting] = useState(false); useEffect(() => { - // Check if already dismissed for this announcement date try { if (localStorage.getItem(STORAGE_KEY) === 'true') return; } catch { - // localStorage unavailable (SSR, private browsing) return; } - const timer = setTimeout(() => setVisible(true), DELAY_MS); return () => clearTimeout(timer); }, []); @@ -31,9 +33,36 @@ export function AnnouncementToast() { setVisible(false); try { localStorage.setItem(STORAGE_KEY, 'true'); - } catch { - // ignore - } + } catch { /* ignore */ } + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + if (!email) return; + setSubmitting(true); + try { + await fetch('/api/whitepaper-signup', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email }), + }); + } catch { /* best-effort */ } + setStep('sent'); + setSubmitting(false); + // Auto-dismiss after showing success + setTimeout(dismiss, 4000); + }; + + const inputStyle: React.CSSProperties = { + width: '100%', + background: 'rgba(255,255,255,0.7)', + border: `1px solid ${tokens.glass.border}`, + borderRadius: 8, + padding: '8px 12px', + fontSize: '0.82rem', + color: tokens.colors.textPrimary, + fontFamily: 'Inter, sans-serif', + outline: 'none', }; return ( @@ -82,7 +111,7 @@ export function AnnouncementToast() { × - {/* Content */} + {/* Eyebrow */}

Free Guide

+ + {/* Title */}

From Prototype to Production

-

- Six production-readiness dimensions for Angular agents. Get the guide. -

-
- (e.currentTarget.style.boxShadow = '0 4px 16px rgba(0,64,144,.3)')} - onMouseLeave={e => (e.currentTarget.style.boxShadow = 'none')} - > - ↓ Download - - -
+ + {step === 'cta' && ( + <> +

+ Six production-readiness dimensions for Angular agents. Get the guide. +

+
+ + +
+ + )} + + {step === 'form' && ( +
+ + setEmail(e.target.value)} + required + disabled={submitting} + autoFocus + style={{ ...inputStyle, marginBottom: 10 }} + onFocus={e => (e.currentTarget.style.borderColor = tokens.colors.accent)} + onBlur={e => (e.currentTarget.style.borderColor = tokens.glass.border)} + /> +
+ +
+ + or download directly + +
+ )} + + {step === 'sent' && ( +
+

+ ✓ Check your inbox — the guide is on its way! +

+
+ )} )}