fix: mobile-responsive nav with hamburger menu at 480px
This commit is contained in:
+258
-133
@@ -1,6 +1,7 @@
|
|||||||
// Top nav — minimal, sticky, blurred
|
// Top nav — minimal, sticky, blurred — mobile-responsive
|
||||||
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
||||||
const [scrolled, setScrolled] = React.useState(false);
|
const [scrolled, setScrolled] = React.useState(false);
|
||||||
|
const [menuOpen, setMenuOpen] = React.useState(false);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const onScroll = () => setScrolled(window.scrollY > 12);
|
const onScroll = () => setScrolled(window.scrollY > 12);
|
||||||
@@ -17,146 +18,270 @@ const Nav = ({ onCmdK, theme, onToggleTheme, accent, lang, onToggleLang }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav style={{
|
<>
|
||||||
position: "fixed",
|
<nav style={{
|
||||||
top: 0,
|
position: "fixed",
|
||||||
left: 0,
|
top: 0,
|
||||||
right: 0,
|
left: 0,
|
||||||
zIndex: 50,
|
right: 0,
|
||||||
borderBottom: scrolled ? "1px solid var(--line)" : "1px solid transparent",
|
zIndex: 50,
|
||||||
background: scrolled ? "color-mix(in srgb, var(--bg) 75%, transparent)" : "transparent",
|
borderBottom: scrolled ? "1px solid var(--line)" : "1px solid transparent",
|
||||||
backdropFilter: scrolled ? "blur(14px)" : "none",
|
background: scrolled ? "color-mix(in srgb, var(--bg) 75%, transparent)" : "transparent",
|
||||||
WebkitBackdropFilter: scrolled ? "blur(14px)" : "none",
|
backdropFilter: scrolled ? "blur(14px)" : "none",
|
||||||
transition: "all 0.25s ease",
|
WebkitBackdropFilter: scrolled ? "blur(14px)" : "none",
|
||||||
}}>
|
transition: "all 0.25s ease",
|
||||||
<div className="container" style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
height: 64,
|
|
||||||
}}>
|
}}>
|
||||||
{/* Brand */}
|
<div className="container" style={{
|
||||||
<a href="#top" style={{ display: "flex", alignItems: "center", gap: 10 }}>
|
display: "flex",
|
||||||
<Icons.Logo size={26} />
|
alignItems: "center",
|
||||||
<span style={{ fontWeight: 600, fontSize: 15, letterSpacing: "-0.01em" }}>{PORTFOLIO_DATA.brand.name}</span>
|
justifyContent: "space-between",
|
||||||
<span style={{
|
height: 64,
|
||||||
fontFamily: "var(--font-mono)",
|
}}>
|
||||||
fontSize: 11,
|
{/* Brand */}
|
||||||
color: "var(--text-faint)",
|
<a href="#top" style={{ display: "flex", alignItems: "center", gap: 10, flexShrink: 0 }}>
|
||||||
padding: "2px 7px",
|
<Icons.Logo size={26} />
|
||||||
border: "1px solid var(--line)",
|
<span style={{ fontWeight: 600, fontSize: 15, letterSpacing: "-0.01em" }}>{PORTFOLIO_DATA.brand.name}</span>
|
||||||
borderRadius: 999,
|
<span className="nav-badge" style={{
|
||||||
marginLeft: 4,
|
fontFamily: "var(--font-mono)",
|
||||||
}}>v.2026</span>
|
fontSize: 11,
|
||||||
</a>
|
color: "var(--text-faint)",
|
||||||
|
padding: "2px 7px",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
|
borderRadius: 999,
|
||||||
|
marginLeft: 4,
|
||||||
|
}}>v.2026</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
{/* Center links */}
|
{/* Center links — hidden on mobile */}
|
||||||
<div style={{ display: "flex", gap: 4, alignItems: "center" }} className="nav-links">
|
<div style={{ display: "flex", gap: 4, alignItems: "center" }} className="nav-links">
|
||||||
{links.map(l => (
|
{links.map(l => (
|
||||||
<a key={l.id} href={`#${l.id}`} style={{
|
<a key={l.id} href={"#" + l.id} style={{
|
||||||
fontSize: 13.5,
|
fontSize: 13.5,
|
||||||
color: "var(--text-dim)",
|
color: "var(--text-dim)",
|
||||||
padding: "6px 12px",
|
padding: "6px 12px",
|
||||||
|
borderRadius: 8,
|
||||||
|
transition: "all 0.15s",
|
||||||
|
}}
|
||||||
|
onMouseEnter={e => { e.currentTarget.style.color = "var(--text)"; e.currentTarget.style.background = "var(--line)"; }}
|
||||||
|
onMouseLeave={e => { e.currentTarget.style.color = "var(--text-dim)"; e.currentTarget.style.background = "transparent"; }}
|
||||||
|
>{l.label}</a>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right — desktop */}
|
||||||
|
<div className="nav-right" style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
||||||
|
<button onClick={onCmdK} className="nav-search-btn" style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8,
|
||||||
|
padding: "6px 8px 6px 12px",
|
||||||
|
background: "transparent",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
transition: "all 0.15s",
|
color: "var(--text-dim)",
|
||||||
|
fontSize: 12.5,
|
||||||
|
}}>
|
||||||
|
<Icons.Search size={13} />
|
||||||
|
<span>Search</span>
|
||||||
|
<kbd style={{
|
||||||
|
fontFamily: "var(--font-mono)",
|
||||||
|
fontSize: 10.5,
|
||||||
|
padding: "2px 5px",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
|
borderRadius: 4,
|
||||||
|
color: "var(--text-faint)",
|
||||||
|
}}>⌘K</kbd>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button onClick={onToggleTheme} aria-label="Toggle theme" style={{
|
||||||
|
width: 34, height: 34,
|
||||||
|
display: "grid", placeItems: "center",
|
||||||
|
background: "transparent",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
|
borderRadius: 8,
|
||||||
|
color: "var(--text-dim)",
|
||||||
|
}}>
|
||||||
|
{theme === "dark" ? <Icons.Sun size={15} /> : <Icons.Moon size={15} />}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button onClick={onToggleLang} className="nav-lang-btn" style={{
|
||||||
|
padding: "6px 10px",
|
||||||
|
background: "transparent",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
|
borderRadius: 8,
|
||||||
|
color: "var(--text-dim)",
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 600,
|
||||||
|
cursor: "pointer",
|
||||||
|
letterSpacing: "0.04em",
|
||||||
|
}}>
|
||||||
|
{lang === "en" ? "বাং" : "EN"}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<a href="mailto:hello@auraajenticai.cloud?subject=Project Quote" className="nav-quote-btn" style={{
|
||||||
|
padding: "7px 13px",
|
||||||
|
background: "transparent",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
|
borderRadius: 8,
|
||||||
|
color: "var(--text-dim)",
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: 500,
|
||||||
|
textDecoration: "none",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
}}>
|
||||||
|
Get a Quote
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://auth.auraajenticai.cloud/login" className="nav-login-btn" style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 6,
|
||||||
|
padding: "8px 14px",
|
||||||
|
background: "var(--text)",
|
||||||
|
color: "var(--bg)",
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: 500,
|
||||||
|
borderRadius: 8,
|
||||||
|
textDecoration: "none",
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
}}>
|
||||||
|
Client Login <Icons.Arrow size={13} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Hamburger — mobile only */}
|
||||||
|
<button
|
||||||
|
className="nav-hamburger"
|
||||||
|
onClick={() => setMenuOpen(o => !o)}
|
||||||
|
aria-label={menuOpen ? "Close menu" : "Open menu"}
|
||||||
|
style={{
|
||||||
|
display: "none",
|
||||||
|
width: 36, height: 36,
|
||||||
|
background: "transparent",
|
||||||
|
border: "1px solid var(--line)",
|
||||||
|
borderRadius: 8,
|
||||||
|
color: "var(--text-dim)",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
flexShrink: 0,
|
||||||
|
cursor: "pointer",
|
||||||
}}
|
}}
|
||||||
onMouseEnter={e => { e.currentTarget.style.color = "var(--text)"; e.currentTarget.style.background = "var(--line)"; }}
|
>
|
||||||
onMouseLeave={e => { e.currentTarget.style.color = "var(--text-dim)"; e.currentTarget.style.background = "transparent"; }}
|
{menuOpen ? (
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||||||
|
<path d="M2 2l12 12M14 2L2 14" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
||||||
|
</svg>
|
||||||
|
) : (
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||||||
|
<path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>{`
|
||||||
|
@media (max-width: 880px) {
|
||||||
|
.nav-links { display: none !important; }
|
||||||
|
}
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.nav-search-btn { display: none !important; }
|
||||||
|
.nav-quote-btn { display: none !important; }
|
||||||
|
.nav-badge { display: none !important; }
|
||||||
|
.nav-lang-btn { display: none !important; }
|
||||||
|
}
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.nav-login-btn { display: none !important; }
|
||||||
|
.nav-hamburger { display: flex !important; }
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{/* Mobile drawer */}
|
||||||
|
{menuOpen && (
|
||||||
|
<div style={{
|
||||||
|
position: "fixed",
|
||||||
|
top: 64,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
zIndex: 49,
|
||||||
|
background: "color-mix(in srgb, var(--bg) 96%, transparent)",
|
||||||
|
backdropFilter: "blur(20px)",
|
||||||
|
WebkitBackdropFilter: "blur(20px)",
|
||||||
|
borderBottom: "1px solid var(--line)",
|
||||||
|
padding: "1rem 20px 1.5rem",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 2,
|
||||||
|
}}>
|
||||||
|
{links.map(l => (
|
||||||
|
<a
|
||||||
|
key={l.id}
|
||||||
|
href={"#" + l.id}
|
||||||
|
onClick={() => setMenuOpen(false)}
|
||||||
|
style={{
|
||||||
|
fontSize: 15,
|
||||||
|
color: "var(--text-dim)",
|
||||||
|
padding: "12px 4px",
|
||||||
|
textDecoration: "none",
|
||||||
|
display: "block",
|
||||||
|
borderBottom: "1px solid var(--line)",
|
||||||
|
}}
|
||||||
>{l.label}</a>
|
>{l.label}</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
<div style={{ display: "flex", gap: 8, marginTop: 14, flexWrap: "wrap" }}>
|
||||||
|
<button onClick={() => { onToggleTheme(); setMenuOpen(false); }} style={{
|
||||||
{/* Right: ⌘K, theme, hire */}
|
padding: "8px 14px",
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
|
background: "transparent",
|
||||||
<button onClick={onCmdK} style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 8,
|
|
||||||
padding: "6px 8px 6px 12px",
|
|
||||||
background: "transparent",
|
|
||||||
border: "1px solid var(--line)",
|
|
||||||
borderRadius: 8,
|
|
||||||
color: "var(--text-dim)",
|
|
||||||
fontSize: 12.5,
|
|
||||||
}}>
|
|
||||||
<Icons.Search size={13} />
|
|
||||||
<span>Search</span>
|
|
||||||
<kbd style={{
|
|
||||||
fontFamily: "var(--font-mono)",
|
|
||||||
fontSize: 10.5,
|
|
||||||
padding: "2px 5px",
|
|
||||||
border: "1px solid var(--line)",
|
border: "1px solid var(--line)",
|
||||||
borderRadius: 4,
|
borderRadius: 8,
|
||||||
color: "var(--text-faint)",
|
color: "var(--text-dim)",
|
||||||
}}>⌘K</kbd>
|
fontSize: 13,
|
||||||
</button>
|
cursor: "pointer",
|
||||||
|
}}>
|
||||||
<button onClick={onToggleTheme} aria-label="Toggle theme" style={{
|
{theme === "dark" ? "Light" : "Dark"}
|
||||||
width: 34, height: 34,
|
</button>
|
||||||
display: "grid", placeItems: "center",
|
<button onClick={() => { onToggleLang(); setMenuOpen(false); }} style={{
|
||||||
background: "transparent",
|
padding: "8px 14px",
|
||||||
border: "1px solid var(--line)",
|
background: "transparent",
|
||||||
borderRadius: 8,
|
border: "1px solid var(--line)",
|
||||||
color: "var(--text-dim)",
|
borderRadius: 8,
|
||||||
}}>
|
color: "var(--text-dim)",
|
||||||
{theme === "dark" ? <Icons.Sun size={15} /> : <Icons.Moon size={15} />}
|
fontSize: 13,
|
||||||
</button>
|
cursor: "pointer",
|
||||||
|
fontWeight: 600,
|
||||||
{/* EN/BN toggle */}
|
}}>
|
||||||
<button onClick={onToggleLang} style={{
|
{lang === "en" ? "বাংলা" : "English"}
|
||||||
padding: "6px 10px",
|
</button>
|
||||||
background: "transparent",
|
<a
|
||||||
border: "1px solid var(--line)",
|
href="mailto:hello@auraajenticai.cloud?subject=Project Quote"
|
||||||
borderRadius: 8,
|
onClick={() => setMenuOpen(false)}
|
||||||
color: "var(--text-dim)",
|
style={{
|
||||||
fontSize: 12,
|
padding: "8px 14px",
|
||||||
fontWeight: 600,
|
background: "transparent",
|
||||||
cursor: "pointer",
|
border: "1px solid var(--line)",
|
||||||
letterSpacing: "0.04em",
|
borderRadius: 8,
|
||||||
}}>
|
color: "var(--text-dim)",
|
||||||
{lang === "en" ? "বাং" : "EN"}
|
fontSize: 13,
|
||||||
</button>
|
textDecoration: "none",
|
||||||
|
}}
|
||||||
{/* Get a Quote */}
|
>Get a Quote</a>
|
||||||
<a href="mailto:hello@auraajenticai.cloud?subject=Project Quote" style={{
|
<a
|
||||||
padding: "7px 13px",
|
href="https://auth.auraajenticai.cloud/login"
|
||||||
background: "transparent",
|
onClick={() => setMenuOpen(false)}
|
||||||
border: "1px solid var(--line)",
|
style={{
|
||||||
borderRadius: 8,
|
padding: "8px 14px",
|
||||||
color: "var(--text-dim)",
|
background: "var(--text)",
|
||||||
fontSize: 13,
|
color: "var(--bg)",
|
||||||
fontWeight: 500,
|
fontSize: 13,
|
||||||
textDecoration: "none",
|
fontWeight: 500,
|
||||||
whiteSpace: "nowrap",
|
borderRadius: 8,
|
||||||
}}>
|
textDecoration: "none",
|
||||||
Get a Quote
|
}}
|
||||||
</a>
|
>Client Login</a>
|
||||||
|
</div>
|
||||||
{/* Client Login */}
|
|
||||||
<a href="https://auth.auraajenticai.cloud/login" style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: 6,
|
|
||||||
padding: "8px 14px",
|
|
||||||
background: "var(--text)",
|
|
||||||
color: "var(--bg)",
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: 500,
|
|
||||||
borderRadius: 8,
|
|
||||||
textDecoration: "none",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
}}>
|
|
||||||
Client Login <Icons.Arrow size={13} />
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
|
</>
|
||||||
<style>{`
|
|
||||||
@media (max-width: 880px) {
|
|
||||||
.nav-links { display: none !important; }
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</nav>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user