Skip to content

Commit 71cb507

Browse files
committed
update: footer design
1 parent 908f898 commit 71cb507

3 files changed

Lines changed: 309 additions & 53 deletions

File tree

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
import { Link } from 'react-router-dom';
2+
import { Github, Twitter, Linkedin, ArrowRight, Database } from 'lucide-react';
3+
4+
export default function Footer() {
5+
return (
6+
<footer className="modern-footer">
7+
<div className="footer-content container">
8+
9+
{/* Top Section: Centered Layout */}
10+
<div className="footer-top">
11+
12+
{/* Brand / Newsletter Column */}
13+
<div className="footer-brand-col">
14+
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '1rem' }}>
15+
<Database size={24} color="var(--color-primary)" />
16+
<span style={{ fontSize: '1.2rem', fontWeight: 700, color: '#fff' }}>urBackend</span>
17+
</div>
18+
<p style={{ color: 'var(--color-text-muted)', marginBottom: '1.5rem', maxWidth: '300px' }}>
19+
The instant Backend-as-a-Service for frontend developers. Ship faster.
20+
</p>
21+
22+
<div className="footer-input-wrapper">
23+
<input type="email" placeholder="Stay up to date" />
24+
<button><ArrowRight size={16} /></button>
25+
</div>
26+
</div>
27+
28+
{/* Navigation Columns */}
29+
<div className="footer-nav-grid">
30+
<div className="footer-col">
31+
<h4>Product</h4>
32+
<Link to="/#features">Database</Link>
33+
<Link to="/#features">Auth</Link>
34+
<Link to="/#features">Storage</Link>
35+
<Link to="/pricing">Pricing</Link>
36+
</div>
37+
<div className="footer-col">
38+
<h4>Resources</h4>
39+
<Link to="/docs">Documentation</Link>
40+
<Link to="/docs">API Reference</Link>
41+
<Link to="/community">Community</Link>
42+
<a href="https://github.com/yash-pouranik" target="_blank" rel="noreferrer">GitHub</a>
43+
</div>
44+
<div className="footer-col">
45+
<h4>Company</h4>
46+
<Link to="/about">About</Link>
47+
<Link to="/blog">Blog</Link>
48+
<Link to="/careers">Careers</Link>
49+
<Link to="/contact">Contact</Link>
50+
</div>
51+
</div>
52+
</div>
53+
54+
{/* Middle: Socials & Legal (Also Centered) */}
55+
<div className="footer-middle">
56+
<div className="social-links">
57+
<a href="#" className="social-icon"><Github size={20} /></a>
58+
<a href="#" className="social-icon"><Twitter size={20} /></a>
59+
<a href="#" className="social-icon"><Linkedin size={20} /></a>
60+
</div>
61+
<div className="legal-links">
62+
<span>&copy; 2025 urBackend Inc.</span>
63+
<Link to="/privacy">Privacy</Link>
64+
<Link to="/terms">Terms</Link>
65+
</div>
66+
</div>
67+
68+
{/* Bottom: Massive Typography */}
69+
<div className="footer-big-text">
70+
URBACKEND
71+
</div>
72+
</div>
73+
74+
{/* --- UPDATED STYLES (Center Aligned) --- */}
75+
<style>{`
76+
.modern-footer {
77+
background-color: #050505;
78+
border-top: 1px solid #222;
79+
padding-top: 6rem;
80+
color: #fff;
81+
overflow: hidden;
82+
position: relative;
83+
}
84+
85+
/* --- KEY FIXES HERE --- */
86+
.footer-top {
87+
display: flex;
88+
flex-wrap: wrap;
89+
justify-content: center; /* Center alignment */
90+
gap: 4rem; /* Reduced from 8rem to prevent wrapping */
91+
margin-bottom: 5rem;
92+
text-align: left; /* Keep text left aligned inside blocks */
93+
}
94+
95+
.footer-brand-col {
96+
flex: 0 1 auto; /* Don't stretch */
97+
min-width: 280px;
98+
}
99+
100+
.footer-nav-grid {
101+
display: flex;
102+
gap: 3rem; /* Reduced from 5rem */
103+
flex-wrap: wrap;
104+
}
105+
/* --------------------- */
106+
107+
/* Input Styles */
108+
.footer-input-wrapper {
109+
display: flex;
110+
background: #1a1a1a;
111+
border: 1px solid #333;
112+
border-radius: 50px;
113+
padding: 6px;
114+
width: 100%; /* Fill column width */
115+
max-width: 320px;
116+
transition: border-color 0.2s;
117+
}
118+
.footer-input-wrapper:focus-within {
119+
border-color: var(--color-primary);
120+
}
121+
.footer-input-wrapper input {
122+
background: transparent;
123+
border: none;
124+
color: #fff;
125+
padding: 0 16px;
126+
flex: 1;
127+
outline: none;
128+
font-size: 0.9rem;
129+
}
130+
.footer-input-wrapper button {
131+
background: #333;
132+
border: none;
133+
color: #fff;
134+
width: 36px;
135+
height: 36px;
136+
border-radius: 50%;
137+
display: flex;
138+
align-items: center;
139+
justify-content: center;
140+
cursor: pointer;
141+
transition: background 0.2s;
142+
}
143+
.footer-input-wrapper button:hover {
144+
background: var(--color-primary);
145+
color: #000;
146+
}
147+
148+
/* Links Styles */
149+
.footer-col h4 {
150+
font-size: 0.75rem;
151+
text-transform: uppercase;
152+
color: #666;
153+
margin-bottom: 1.2rem;
154+
font-weight: 700;
155+
letter-spacing: 1px;
156+
}
157+
.footer-col {
158+
display: flex;
159+
flex-direction: column;
160+
gap: 12px;
161+
}
162+
.footer-col a {
163+
color: #ccc;
164+
text-decoration: none;
165+
font-size: 0.95rem;
166+
transition: color 0.2s;
167+
}
168+
.footer-col a:hover {
169+
color: #fff;
170+
}
171+
172+
/* Middle Section */
173+
.footer-middle {
174+
display: flex;
175+
justify-content: center; /* Centered */
176+
gap: 4rem; /* Gap between Socials and Legal */
177+
align-items: center;
178+
padding-bottom: 3rem;
179+
border-bottom: 1px solid #222;
180+
flex-wrap: wrap;
181+
}
182+
.social-links { display: flex; gap: 1.5rem; }
183+
.social-icon { color: #666; transition: 0.2s; }
184+
.social-icon:hover { color: #fff; }
185+
186+
.legal-links {
187+
display: flex;
188+
gap: 2rem;
189+
font-size: 0.85rem;
190+
color: #666;
191+
}
192+
.legal-links a { color: #666; text-decoration: none; }
193+
.legal-links a:hover { color: #fff; }
194+
195+
/* BIG TEXT */
196+
.footer-big-text {
197+
font-size: clamp(3rem, 15vw, 12rem); /* Slightly reduced max size */
198+
font-weight: 900;
199+
color: rgba(255, 255, 255, 0.03); /* Subtle opacity */
200+
background: linear-gradient(180deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0) 100%); /* Optional gradient effect */
201+
-webkit-background-clip: text;
202+
background-clip: text;
203+
line-height: 0.8;
204+
text-align: center;
205+
margin-top: 1rem;
206+
margin-bottom: -2%;
207+
letter-spacing: -0.04em;
208+
pointer-events: none;
209+
user-select: none;
210+
}
211+
212+
/* Mobile Tweaks */
213+
@media (max-width: 900px) {
214+
.footer-top {
215+
flex-direction: column;
216+
align-items: center;
217+
text-align: center;
218+
gap: 3rem;
219+
}
220+
.footer-brand-col {
221+
display: flex;
222+
flex-direction: column;
223+
align-items: center;
224+
}
225+
.footer-nav-grid {
226+
gap: 3rem;
227+
justify-content: center;
228+
text-align: center; /* Center links on mobile for better symmetry */
229+
}
230+
/* If using left align on mobile, ensure consistent width */
231+
/* .footer-nav-grid { text-align: left; } */
232+
233+
.footer-middle {
234+
flex-direction: column;
235+
gap: 2rem;
236+
}
237+
}
238+
`}</style>
239+
</footer>
240+
);
241+
}

‎frontend/src/pages/Docs.jsx‎

Lines changed: 59 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { useState } from 'react';
22
import { Copy, Terminal, Database, Shield, HardDrive, Check, Server, Menu, X, ChevronDown, AlertCircle, Zap } from 'lucide-react';
33
import { API_URL } from '../config';
44

5+
import Footer from '../components/Layout/Footer';
6+
57
export default function Docs() {
68
const [activeTab, setActiveTab] = useState('intro');
79
const [isMenuOpen, setIsMenuOpen] = useState(false);
@@ -335,61 +337,62 @@ console.log("File URL:", result.url);
335337
};
336338

337339
return (
338-
<div className="docs-container container">
339-
340-
{/* --- MOBILE TOGGLE --- */}
341-
<div className="docs-mobile-header">
342-
<button onClick={() => setIsMenuOpen(!isMenuOpen)} className="btn btn-secondary" style={{ width: '100%', justifyContent: 'space-between' }}>
343-
<span style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
344-
<Menu size={16} />
345-
{activeTab.charAt(0).toUpperCase() + activeTab.slice(1)}
346-
</span>
347-
<ChevronDown size={16} style={{ transform: isMenuOpen ? 'rotate(180deg)' : 'rotate(0)', transition: '0.2s' }} />
348-
</button>
349-
</div>
340+
<>
341+
<div className="docs-container container">
342+
343+
{/* --- MOBILE TOGGLE --- */}
344+
<div className="docs-mobile-header">
345+
<button onClick={() => setIsMenuOpen(!isMenuOpen)} className="btn btn-secondary" style={{ width: '100%', justifyContent: 'space-between' }}>
346+
<span style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
347+
<Menu size={16} />
348+
{activeTab.charAt(0).toUpperCase() + activeTab.slice(1)}
349+
</span>
350+
<ChevronDown size={16} style={{ transform: isMenuOpen ? 'rotate(180deg)' : 'rotate(0)', transition: '0.2s' }} />
351+
</button>
352+
</div>
350353

351-
{/* --- LEFT SIDEBAR (Navigation) --- */}
352-
<div className={`docs-sidebar ${isMenuOpen ? 'open' : ''}`}>
353-
<h3 className="docs-nav-title">
354-
Documentation
355-
</h3>
356-
<ul style={{ listStyle: 'none', padding: 0 }}>
357-
{[
358-
{ id: 'intro', label: 'Introduction', icon: Terminal },
359-
{ id: 'limits', label: 'Limits & Quotas', icon: AlertCircle }, // New Tab
360-
{ id: 'auth', label: 'Authentication', icon: Shield },
361-
{ id: 'data', label: 'Database & API', icon: Database },
362-
{ id: 'storage', label: 'Storage', icon: HardDrive },
363-
].map(item => (
364-
<li key={item.id} style={{ marginBottom: '4px' }}>
365-
<button
366-
onClick={() => {
367-
setActiveTab(item.id);
368-
setIsMenuOpen(false);
369-
}}
370-
className={`btn ${activeTab === item.id ? 'btn-primary' : 'btn-ghost'}`}
371-
style={{
372-
width: '100%',
373-
justifyContent: 'flex-start',
374-
backgroundColor: activeTab === item.id ? 'rgba(62, 207, 142, 0.1)' : 'transparent',
375-
color: activeTab === item.id ? 'var(--color-primary)' : 'var(--color-text-muted)',
376-
fontWeight: activeTab === item.id ? 600 : 400
377-
}}
378-
>
379-
<item.icon size={16} /> {item.label}
380-
</button>
381-
</li>
382-
))}
383-
</ul>
384-
</div>
354+
{/* --- LEFT SIDEBAR (Navigation) --- */}
355+
<div className={`docs-sidebar ${isMenuOpen ? 'open' : ''}`}>
356+
<h3 className="docs-nav-title">
357+
Documentation
358+
</h3>
359+
<ul style={{ listStyle: 'none', padding: 0 }}>
360+
{[
361+
{ id: 'intro', label: 'Introduction', icon: Terminal },
362+
{ id: 'limits', label: 'Limits & Quotas', icon: AlertCircle }, // New Tab
363+
{ id: 'auth', label: 'Authentication', icon: Shield },
364+
{ id: 'data', label: 'Database & API', icon: Database },
365+
{ id: 'storage', label: 'Storage', icon: HardDrive },
366+
].map(item => (
367+
<li key={item.id} style={{ marginBottom: '4px' }}>
368+
<button
369+
onClick={() => {
370+
setActiveTab(item.id);
371+
setIsMenuOpen(false);
372+
}}
373+
className={`btn ${activeTab === item.id ? 'btn-primary' : 'btn-ghost'}`}
374+
style={{
375+
width: '100%',
376+
justifyContent: 'flex-start',
377+
backgroundColor: activeTab === item.id ? 'rgba(62, 207, 142, 0.1)' : 'transparent',
378+
color: activeTab === item.id ? 'var(--color-primary)' : 'var(--color-text-muted)',
379+
fontWeight: activeTab === item.id ? 600 : 400
380+
}}
381+
>
382+
<item.icon size={16} /> {item.label}
383+
</button>
384+
</li>
385+
))}
386+
</ul>
387+
</div>
385388

386-
{/* --- RIGHT CONTENT --- */}
387-
<div className="docs-content">
388-
{renderContent()}
389-
</div>
389+
{/* --- RIGHT CONTENT --- */}
390+
<div className="docs-content">
391+
{renderContent()}
392+
</div>
390393

391-
{/* --- RESPONSIVE STYLES --- */}
392-
<style>{`
394+
{/* --- RESPONSIVE STYLES --- */}
395+
<style>{`
393396
.docs-container {
394397
display: flex;
395398
gap: 3rem;
@@ -450,6 +453,9 @@ console.log("File URL:", result.url);
450453
}
451454
}
452455
`}</style>
453-
</div>
456+
457+
</div>
458+
<Footer />
459+
</>
454460
);
455461
}

0 commit comments

Comments
 (0)