Skip to content

Commit d5e6588

Browse files
committed
Add Toast in the newsletter
1 parent 93ed237 commit d5e6588

File tree

2 files changed

+182
-29
lines changed

2 files changed

+182
-29
lines changed

src/theme/Footer/Layout/enhanced-footer.css

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,3 +1729,88 @@ html[data-theme='light'] .enhanced-footer {
17291729
.stat-item:nth-child(2) { animation-delay: 0.2s; }
17301730
.stat-item:nth-child(3) { animation-delay: 0.3s; }
17311731
.stat-item:nth-child(4) { animation-delay: 0.4s; }
1732+
1733+
1734+
/* Toast Notification Styles */
1735+
.newsletter-toast {
1736+
position: fixed;
1737+
bottom: 20px;
1738+
right: 20px;
1739+
z-index: 9999;
1740+
animation: slideIn 0.3s ease-out;
1741+
isolation: isolate;
1742+
}
1743+
1744+
.toast-content {
1745+
display: flex;
1746+
align-items: center;
1747+
background: #ffffff !important; /* solid white */
1748+
border-radius: 8px;
1749+
padding: 16px;
1750+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
1751+
border-left: 4px solid #4CAF50;
1752+
max-width: 350px;
1753+
opacity: 1 !important;
1754+
}
1755+
1756+
1757+
.toast-icon {
1758+
font-size: 24px;
1759+
margin-right: 12px;
1760+
}
1761+
1762+
.toast-message h4 {
1763+
margin: 0 0 4px 0;
1764+
font-size: 16px;
1765+
color: #2c3e50;
1766+
}
1767+
1768+
.toast-message p {
1769+
margin: 0;
1770+
font-size: 14px;
1771+
color: #7f8c8d;
1772+
}
1773+
1774+
.toast-close {
1775+
background: none;
1776+
border: none;
1777+
font-size: 20px;
1778+
cursor: pointer;
1779+
margin-left: 16px;
1780+
color: #95a5a6;
1781+
padding: 0;
1782+
width: 24px;
1783+
height: 24px;
1784+
display: flex;
1785+
align-items: center;
1786+
justify-content: center;
1787+
border-radius: 50%;
1788+
}
1789+
1790+
.toast-close:hover {
1791+
background: #f8f9fa;
1792+
color: #2c3e50;
1793+
}
1794+
1795+
@keyframes slideIn {
1796+
from {
1797+
transform: translateX(100%);
1798+
opacity: 0;
1799+
}
1800+
to {
1801+
transform: translateX(0);
1802+
opacity: 1;
1803+
}
1804+
}
1805+
1806+
@media (max-width: 768px) {
1807+
.newsletter-toast {
1808+
bottom: 10px;
1809+
right: 10px;
1810+
left: 10px;
1811+
}
1812+
1813+
.toast-content {
1814+
max-width: none;
1815+
}
1816+
}

src/theme/Footer/Layout/index.tsx

Lines changed: 97 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
21
import React, {type ReactNode, useState, useEffect} from 'react';
32
import Link from "@docusaurus/Link";
43
import type {Props} from '@theme/Footer/Layout';
54
import './enhanced-footer.css';
65
import Counter from './Counter';
6+
import { createPortal } from "react-dom";
7+
78

89
// Dynamic stats interface
910
interface FooterStats {
@@ -28,6 +29,7 @@ export default function FooterLayout({
2829
});
2930
const [email, setEmail] = useState('');
3031
const [isSubscribed, setIsSubscribed] = useState(false);
32+
const [showToast, setShowToast] = useState(false);
3133

3234
useEffect(() => {
3335
// Simulate real-time stats updates
@@ -59,22 +61,57 @@ export default function FooterLayout({
5961
e.preventDefault();
6062
if (email) {
6163
setIsSubscribed(true);
64+
setShowToast(true);
65+
66+
// Hide toast after 3 seconds
67+
setTimeout(() => {
68+
setShowToast(false);
69+
}, 3000);
70+
71+
// Reset form after 3 seconds
6272
setTimeout(() => {
6373
setIsSubscribed(false);
6474
setEmail('');
6575
}, 3000);
6676
}
6777
};
78+
6879
return (
6980
<footer className="enhanced-footer">
81+
{/* Toast Notification */}
82+
{showToast &&
83+
createPortal(
84+
<div className="newsletter-toast">
85+
<div className="toast-content">
86+
<span className="toast-icon">🎉</span>
87+
<div className="toast-message">
88+
<h4>Successfully Subscribed!</h4>
89+
<p>Thank you for joining our newsletter.</p>
90+
</div>
91+
<button
92+
className="toast-close"
93+
onClick={() => setShowToast(false)}
94+
aria-label="Close notification"
95+
>
96+
×
97+
</button>
98+
</div>
99+
</div>,
100+
document.body // 👈 mounts toast directly to <body>, outside footer
101+
)}
102+
70103
{/* Hero Section */}
71104
<div className="footer-hero">
72105
<div className="container">
73106
<div className="footer-hero-content">
74107
<div className="footer-logo-section">
75108
<div className="footer-logo">
76109
<div className="logo-container">
77-
<img src="/img/logo.png" alt="recodehive" className="footer-logo-img" />
110+
<img
111+
src="/img/logo.png"
112+
alt="recodehive"
113+
className="footer-logo-img"
114+
/>
78115
</div>
79116
<div className="footer-brand-header">
80117
<h1 className="footer-brand-title">recodehive</h1>
@@ -86,37 +123,49 @@ export default function FooterLayout({
86123
<span className="star"></span>
87124
<span className="star"></span>
88125
</div>
89-
<span className="trust-text">Trusted by 50K+ developers</span>
126+
<span className="trust-text">
127+
Trusted by 50K+ developers
128+
</span>
90129
</div>
91130
</div>
92131
</div>
93132
</div>
94133
<div className="footer-hero-text">
95134
<h1>Empowering the Next Generation of Developers</h1>
96-
<p>Master cutting-edge technologies, build innovative projects, and join a thriving community of developers passionate about open-source innovation and continuous learning.</p>
135+
<p>
136+
Master cutting-edge technologies, build innovative projects, and
137+
join a thriving community of developers passionate about
138+
open-source innovation and continuous learning.
139+
</p>
97140
</div>
98141
</div>
99142

100143
{/* Stats Section */}
101144
<div className="footer-stats">
102-
<div className="stat-item" title="Growing community of active learners">
145+
<div
146+
className="stat-item"
147+
title="Growing community of active learners"
148+
>
103149
<div className="stat-icon stat-icon-learners">
104150
<svg viewBox="0 0 24 24" fill="currentColor">
105-
<path d="M16 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2-2zM4 18v-6h2.5l6 6H4zm16.5-9.5L19 7l-7.5 7.5L9 12l-2.5 2.5L4 12l7.5-7.5L14 7l6.5 1.5z"/>
151+
<path d="M16 4c0-1.11.89-2 2-2s2 .89 2 2-.89 2-2 2-2-.89-2-2zM4 18v-6h2.5l6 6H4zm16.5-9.5L19 7l-7.5 7.5L9 12l-2.5 2.5L4 12l7.5-7.5L14 7l6.5 1.5z" />
106152
</svg>
107153
</div>
108154
<div className="stat-content">
109155
<div className="stat-number">
110-
<Counter value={parseInt(stats.activeUsers)} suffix="K+" />
156+
<Counter value={parseInt(stats.activeUsers)} suffix="K+" />
111157
</div>
112158
<div className="stat-label">Active Learners</div>
113159
</div>
114160
</div>
115161

116-
<div className="stat-item" title="Comprehensive tutorials and courses">
162+
<div
163+
className="stat-item"
164+
title="Comprehensive tutorials and courses"
165+
>
117166
<div className="stat-icon stat-icon-tutorials">
118167
<svg viewBox="0 0 24 24" fill="currentColor">
119-
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/>
168+
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z" />
120169
</svg>
121170
</div>
122171
<div className="stat-content">
@@ -127,10 +176,13 @@ export default function FooterLayout({
127176
</div>
128177
</div>
129178

130-
<div className="stat-item" title="High success rate in learning outcomes">
179+
<div
180+
className="stat-item"
181+
title="High success rate in learning outcomes"
182+
>
131183
<div className="stat-icon stat-icon-success">
132184
<svg viewBox="0 0 24 24" fill="currentColor">
133-
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
185+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
134186
</svg>
135187
</div>
136188
<div className="stat-content">
@@ -141,10 +193,13 @@ export default function FooterLayout({
141193
</div>
142194
</div>
143195

144-
<div className="stat-item" title="Round-the-clock community support">
196+
<div
197+
className="stat-item"
198+
title="Round-the-clock community support"
199+
>
145200
<div className="stat-icon stat-icon-support">
146201
<svg viewBox="0 0 24 24" fill="currentColor">
147-
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-6h2v6zm0-8h-2V7h2v4z"/>
202+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-6h2v6zm0-8h-2V7h2v4z" />
148203
</svg>
149204
</div>
150205
<div className="stat-content">
@@ -169,7 +224,6 @@ export default function FooterLayout({
169224
<ul className="footer-links">
170225
<li>
171226
<Link to="#" className="footer-link">
172-
173227
<span className="link-icon">📖</span>
174228
Documentation
175229
<span className="link-badge popular">Popular</span>
@@ -271,7 +325,6 @@ export default function FooterLayout({
271325
</Link>
272326
</li>
273327
</ul>
274-
275328
</div>
276329

277330
{/* Newsletter Column with Quick Links below */}
@@ -281,7 +334,8 @@ export default function FooterLayout({
281334
Stay in the Loop
282335
</h3>
283336
<p className="newsletter-description">
284-
Join {stats.activeUsers} developers getting weekly insights, tutorials, and exclusive content.
337+
Join {stats.activeUsers} developers getting weekly insights,
338+
tutorials, and exclusive content.
285339
</p>
286340
<form className="newsletter-form" onSubmit={handleSubscribe}>
287341
<input
@@ -294,14 +348,18 @@ export default function FooterLayout({
294348
/>
295349
<button
296350
type="submit"
297-
className={`newsletter-button ${isSubscribed ? 'subscribed' : ''}`}
351+
className={`newsletter-button ${
352+
isSubscribed ? "subscribed" : ""
353+
}`}
298354
disabled={isSubscribed}
299355
>
300-
{isSubscribed ? '✓ Subscribed!' : 'Subscribe Now →'}
356+
{isSubscribed ? "✓ Subscribed!" : "Subscribe Now →"}
301357
</button>
302358
</form>
303359
<div className="newsletter-stats">
304-
<span className="newsletter-stat">📊 1.2K+ developers joined this week</span>
360+
<span className="newsletter-stat">
361+
📊 1.2K+ developers joined this week
362+
</span>
305363
</div>
306364
{/* Quick Links Section moved below subscription */}
307365
<div className="quick-links-section newsletter-quick-links">
@@ -338,7 +396,7 @@ export default function FooterLayout({
338396
aria-label="GitHub"
339397
>
340398
<svg viewBox="0 0 24 24" fill="currentColor">
341-
<path d="M12 0C5.37 0 0 5.37 0 12C0 17.31 3.435 21.795 8.205 23.385C8.805 23.49 9.03 23.13 9.03 22.815C9.03 22.53 9.015 21.585 9.015 20.58C6 21.135 5.22 19.845 4.98 19.17C4.845 18.825 4.26 17.76 3.75 17.475C3.33 17.25 2.73 16.695 3.735 16.68C4.68 16.665 5.355 17.55 5.58 17.91C6.66 19.725 8.385 19.215 9.075 18.9C9.18 18.12 9.495 17.595 9.84 17.295C7.17 16.995 4.38 15.96 4.38 11.37C4.38 10.065 4.845 8.985 5.61 8.145C5.49 7.845 5.07 6.615 5.73 4.965C5.73 4.965 6.735 4.65 9.03 6.195C9.99 5.925 11.01 5.79 12.03 5.79C13.05 5.79 14.07 5.925 15.03 6.195C17.325 4.635 18.33 4.965 18.33 4.965C18.99 6.615 18.57 7.845 18.45 8.145C19.215 8.985 19.68 10.05 19.68 11.37C19.68 15.975 16.875 16.995 14.205 17.295C14.64 17.67 15.015 18.39 15.015 19.515C15.015 21.12 15 22.41 15 22.815C15 23.13 15.225 23.505 15.825 23.385C18.2072 22.5807 20.2772 21.0497 21.7437 19.0074C23.2101 16.965 23.9993 14.5143 24 12C24 5.37 18.63 0 12 0Z"/>
399+
<path d="M12 0C5.37 0 0 5.37 0 12C0 17.31 3.435 21.795 8.205 23.385C8.805 23.49 9.03 23.13 9.03 22.815C9.03 22.53 9.015 21.585 9.015 20.58C6 21.135 5.22 19.845 4.98 19.17C4.845 18.825 4.26 17.76 3.75 17.475C3.33 17.25 2.73 16.695 3.735 16.68C4.68 16.665 5.355 17.55 5.58 17.91C6.66 19.725 8.385 19.215 9.075 18.9C9.18 18.12 9.495 17.595 9.84 17.295C7.17 16.995 4.38 15.96 4.38 11.37C4.38 10.065 4.845 8.985 5.61 8.145C5.49 7.845 5.07 6.615 5.73 4.965C5.73 4.965 6.735 4.65 9.03 6.195C9.99 5.925 11.01 5.79 12.03 5.79C13.05 5.79 14.07 5.925 15.03 6.195C17.325 4.635 18.33 4.965 18.33 4.965C18.99 6.615 18.57 7.845 18.45 8.145C19.215 8.985 19.68 10.05 19.68 11.37C19.68 15.975 16.875 16.995 14.205 17.295C14.64 17.67 15.015 18.39 15.015 19.515C15.015 21.12 15 22.41 15 22.815C15 23.13 15.225 23.505 15.825 23.385C18.2072 22.5807 20.2772 21.0497 21.7437 19.0074C23.2101 16.965 23.9993 14.5143 24 12C24 5.37 18.63 0 12 0Z" />
342400
</svg>
343401
</Link>
344402

@@ -348,7 +406,7 @@ export default function FooterLayout({
348406
aria-label="Twitter"
349407
>
350408
<svg viewBox="0 0 24 24" fill="currentColor">
351-
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
409+
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
352410
</svg>
353411
</Link>
354412

@@ -358,7 +416,7 @@ export default function FooterLayout({
358416
aria-label="Instagram"
359417
>
360418
<svg viewBox="0 0 24 24" fill="currentColor">
361-
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
419+
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" />
362420
</svg>
363421
</Link>
364422

@@ -368,29 +426,39 @@ export default function FooterLayout({
368426
aria-label="LinkedIn"
369427
>
370428
<svg viewBox="0 0 24 24" fill="currentColor">
371-
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
429+
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" />
372430
</svg>
373431
</Link>
374432
</div>
375433
</div>
376434

377435
<div className="footer-bottom-center">
378436
<div className="footer-legal-links">
379-
<Link to="/privacy-policy" className="legal-link">Privacy Policy</Link>
380-
<Link to="/terms-service" className="legal-link">Terms of Service</Link>
381-
<Link to="/code-of-conduct" className="legal-link">Code of Conduct</Link>
382-
<Link to="/License" className="legal-link">License</Link>
437+
<Link to="/privacy-policy" className="legal-link">
438+
Privacy Policy
439+
</Link>
440+
<Link to="/terms-service" className="legal-link">
441+
Terms of Service
442+
</Link>
443+
<Link to="/code-of-conduct" className="legal-link">
444+
Code of Conduct
445+
</Link>
446+
<Link to="/License" className="legal-link">
447+
License
448+
</Link>
383449
</div>
384450
</div>
385451

386452
<div className="footer-bottom-right">
387453
<div className="footer-copyright">
388-
<span>© {currentYear} recodehive. Made with ❤️ by the Community.</span>
454+
<span>
455+
© {currentYear} recodehive. Made with ❤️ by the Community.
456+
</span>
389457
</div>
390458
</div>
391459
</div>
392460
</div>
393461
</div>
394462
</footer>
395463
);
396-
}
464+
}

0 commit comments

Comments
 (0)