Implement achraf's portfolio
This commit is contained in:
219
components/Navigation.tsx
Normal file
219
components/Navigation.tsx
Normal file
@@ -0,0 +1,219 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const links = [
|
||||
{ label: "Projects", href: "#projects" },
|
||||
{ label: "Experience", href: "#experience" },
|
||||
{ label: "Education", href: "#education" },
|
||||
{ label: "Skills", href: "#skills" },
|
||||
{ label: "Contact", href: "#contact" },
|
||||
];
|
||||
|
||||
export default function Navigation() {
|
||||
const [scrolled, setScrolled] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [active, setActive] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const onScroll = () => setScrolled(window.scrollY > 60);
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
return () => window.removeEventListener("scroll", onScroll);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<header
|
||||
style={{
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 100,
|
||||
transition: "background 0.4s ease, border-color 0.4s ease",
|
||||
background: scrolled ? "rgba(7,8,10,0.94)" : "transparent",
|
||||
backdropFilter: scrolled ? "blur(16px)" : "none",
|
||||
borderBottom: scrolled ? "1px solid #1c1f26" : "1px solid transparent",
|
||||
}}
|
||||
>
|
||||
<nav
|
||||
style={{
|
||||
maxWidth: "1200px",
|
||||
margin: "0 auto",
|
||||
padding: "0 2.5rem",
|
||||
height: "68px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
{/* Logo */}
|
||||
<a href="#hero" style={{ textDecoration: "none", flexShrink: 0 }}>
|
||||
<div
|
||||
style={{
|
||||
width: "38px",
|
||||
height: "38px",
|
||||
border: "1px solid #c8a96e",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontFamily: "var(--font-bebas), sans-serif",
|
||||
fontSize: "1.15rem",
|
||||
color: "#c8a96e",
|
||||
letterSpacing: "0.04em",
|
||||
transition: "background 0.2s, box-shadow 0.2s",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = "rgba(200,169,110,0.1)";
|
||||
e.currentTarget.style.boxShadow = "0 0 16px rgba(200,169,110,0.15)";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = "transparent";
|
||||
e.currentTarget.style.boxShadow = "none";
|
||||
}}
|
||||
>
|
||||
AA
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{/* Desktop links — each wrapped for padding & underline */}
|
||||
<div
|
||||
className="hidden md:flex"
|
||||
style={{ alignItems: "center", gap: "0" }}
|
||||
>
|
||||
{links.map((l, i) => (
|
||||
<a
|
||||
key={l.href}
|
||||
href={l.href}
|
||||
onClick={() => setActive(l.href)}
|
||||
style={{
|
||||
fontFamily: "var(--font-jetbrains), monospace",
|
||||
fontSize: "0.72rem",
|
||||
letterSpacing: "0.16em",
|
||||
textTransform: "uppercase",
|
||||
textDecoration: "none",
|
||||
padding: "0.5rem 1.4rem",
|
||||
color: active === l.href ? "#c8a96e" : "#4a5060",
|
||||
position: "relative",
|
||||
transition: "color 0.2s",
|
||||
borderLeft: i > 0 ? "1px solid #1c1f26" : "none",
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.color = "#c8a96e";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
(e.currentTarget as HTMLElement).style.color =
|
||||
active === l.href ? "#c8a96e" : "#4a5060";
|
||||
}}
|
||||
>
|
||||
{l.label}
|
||||
{/* bottom accent line on hover */}
|
||||
<span
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
left: "1.4rem",
|
||||
right: "1.4rem",
|
||||
height: "1px",
|
||||
background: "#c8a96e",
|
||||
transform: "scaleX(0)",
|
||||
transformOrigin: "left",
|
||||
transition: "transform 0.25s ease",
|
||||
}}
|
||||
className="nav-underline"
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Mobile toggle */}
|
||||
<button
|
||||
onClick={() => setOpen(!open)}
|
||||
className="md:hidden flex flex-col"
|
||||
style={{
|
||||
background: "none",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
padding: "8px",
|
||||
gap: "5px",
|
||||
}}
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<span
|
||||
style={{
|
||||
display: "block",
|
||||
width: "22px",
|
||||
height: "1px",
|
||||
background: "#c8a96e",
|
||||
transition: "transform 0.25s ease",
|
||||
transform: open ? "translateY(6px) rotate(45deg)" : "none",
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
style={{
|
||||
display: "block",
|
||||
width: "22px",
|
||||
height: "1px",
|
||||
background: "#c8a96e",
|
||||
transition: "opacity 0.2s",
|
||||
opacity: open ? 0 : 1,
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
style={{
|
||||
display: "block",
|
||||
width: "22px",
|
||||
height: "1px",
|
||||
background: "#c8a96e",
|
||||
transition: "transform 0.25s ease",
|
||||
transform: open ? "translateY(-6px) rotate(-45deg)" : "none",
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
{/* Hover underline via CSS */}
|
||||
<style>{`
|
||||
nav a:hover .nav-underline { transform: scaleX(1) !important; }
|
||||
`}</style>
|
||||
|
||||
{/* Mobile menu */}
|
||||
<div
|
||||
style={{
|
||||
background: "rgba(7,8,10,0.98)",
|
||||
borderTop: "1px solid #1c1f26",
|
||||
overflow: "hidden",
|
||||
maxHeight: open ? "320px" : "0",
|
||||
transition: "max-height 0.3s ease",
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: "1.5rem 2.5rem", display: "flex", flexDirection: "column", gap: "0" }}>
|
||||
{links.map((l, i) => (
|
||||
<a
|
||||
key={l.href}
|
||||
href={l.href}
|
||||
onClick={() => setOpen(false)}
|
||||
style={{
|
||||
fontFamily: "var(--font-jetbrains), monospace",
|
||||
fontSize: "0.78rem",
|
||||
letterSpacing: "0.16em",
|
||||
textTransform: "uppercase",
|
||||
textDecoration: "none",
|
||||
padding: "1rem 0",
|
||||
color: "#4a5060",
|
||||
borderBottom: i < links.length - 1 ? "1px solid #1c1f26" : "none",
|
||||
transition: "color 0.2s",
|
||||
}}
|
||||
onMouseEnter={(e) => (e.currentTarget.style.color = "#c8a96e")}
|
||||
onMouseLeave={(e) => (e.currentTarget.style.color = "#4a5060")}
|
||||
>
|
||||
<span style={{ color: "#c8a96e", marginRight: "0.75rem", fontSize: "0.6rem" }}>
|
||||
{String(i + 1).padStart(2, "0")}
|
||||
</span>
|
||||
{l.label}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user