|
import React, { useState, useEffect, useRef } from "react"; |
|
import { Link, useLocation } from "react-router-dom"; |
|
import { Logo } from "../utils"; |
|
import styled from "styled-components"; |
|
|
|
|
|
const HeaderContainer = styled.header` |
|
z-index: 500; |
|
background: rgba(0, 0, 0, 0.8); |
|
font-family: "SF Pro", sans-serif; |
|
font-weight: 800; |
|
font-size: 15px; |
|
position: sticky; |
|
top: 0; |
|
width: 100%; |
|
margin: 0; |
|
padding: 0; |
|
`; |
|
|
|
const NavWrapper = styled.div` |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
padding: 0.5rem 1rem; |
|
width: 100%; |
|
margin: 0; |
|
|
|
@media (max-width: 768px) { |
|
justify-content: space-between; |
|
} |
|
`; |
|
|
|
const SLogo = styled(Link)` |
|
display: flex; |
|
align-items: center; |
|
font-weight: bold; |
|
color: white; |
|
text-decoration: none; |
|
|
|
img { |
|
height: 50px; |
|
margin-right: 0.5rem; |
|
} |
|
`; |
|
|
|
const DesktopMenu = styled.nav` |
|
display: none; |
|
|
|
@media (min-width: 768px) { |
|
display: flex; |
|
gap: 1rem; |
|
} |
|
`; |
|
|
|
const MenuLink = styled(Link)` |
|
color: ${(props) => (props.$active ? "transparent" : "white")}; |
|
padding: 0.5rem 2rem; |
|
text-decoration: none; |
|
position: relative; |
|
|
|
@media (min-width: 992px) { |
|
padding: 0.5rem 4rem; |
|
} |
|
|
|
&:hover, |
|
&:active { |
|
color: #3267B9; |
|
background-clip: text; |
|
-webkit-background-clip: text; |
|
} |
|
|
|
${(props) => |
|
props.$active && |
|
` |
|
color: #3267B9; |
|
background-clip: text; |
|
-webkit-background-clip: text; |
|
`} |
|
`; |
|
|
|
const MobileMenuButton = styled.button` |
|
display: block; |
|
background: none; |
|
border: none; |
|
color: white; |
|
font-size: 2.5rem; |
|
cursor: pointer; |
|
transition: transform 0.2s ease; |
|
|
|
&:hover { |
|
color: #0ea8b6; |
|
} |
|
|
|
&:active { |
|
transform: scale(0.9); |
|
} |
|
|
|
@media (min-width: 768px) { |
|
display: none; |
|
} |
|
`; |
|
|
|
const MobileMenu = styled.nav` |
|
background: rgba(0, 0, 0, 0.9); |
|
position: absolute; |
|
top: 100%; |
|
left: 0; |
|
width: 100%; |
|
max-height: ${(props) => (props.$isOpen ? "400px" : "0")}; |
|
overflow: hidden; |
|
opacity: ${(props) => (props.$isOpen ? 1 : 0)}; |
|
transform: ${(props) => (props.$isOpen ? "translateY(0)" : "translateY(-10px)")}; |
|
transition: max-height 0.3s ease, opacity 0.3s ease, transform 0.3s ease; |
|
|
|
a { |
|
display: block; |
|
padding: 0.5rem 1rem; |
|
color: white; |
|
text-decoration: none; |
|
|
|
&:hover { |
|
background: #333; |
|
} |
|
} |
|
`; |
|
|
|
const Header = () => { |
|
const [isMenuOpen, setIsMenuOpen] = useState(false); |
|
const location = useLocation(); |
|
const menuRef = useRef(null); |
|
const buttonRef = useRef(null); |
|
|
|
const toggleMenu = () => setIsMenuOpen(prev => !prev); |
|
|
|
|
|
useEffect(() => { |
|
const handleClickOutside = (event) => { |
|
if ( |
|
menuRef.current && |
|
!menuRef.current.contains(event.target) && |
|
buttonRef.current && |
|
!buttonRef.current.contains(event.target) |
|
) { |
|
setIsMenuOpen(false); |
|
} |
|
}; |
|
|
|
document.addEventListener("mousedown", handleClickOutside); |
|
return () => { |
|
document.removeEventListener("mousedown", handleClickOutside); |
|
}; |
|
}, []); |
|
|
|
|
|
useEffect(() => { |
|
setIsMenuOpen(false); |
|
}, [location.pathname]); |
|
|
|
return ( |
|
<HeaderContainer> |
|
<NavWrapper> |
|
<SLogo to="/"> |
|
<img src={Logo} alt="Logo" /> |
|
</SLogo> |
|
|
|
<DesktopMenu> |
|
{["/vardig", "/about", "/blogs", "/jobs", "/contact"].map((path, i) => ( |
|
<MenuLink key={i} to={path} $active={location.pathname === path}> |
|
{path === "/vardig" |
|
? "VarDiG" |
|
: path.replace("/", "").charAt(0).toUpperCase() + |
|
path.replace("/", "").slice(1)} |
|
</MenuLink> |
|
))} |
|
</DesktopMenu> |
|
|
|
<MobileMenuButton |
|
onClick={toggleMenu} |
|
aria-expanded={isMenuOpen} |
|
ref={buttonRef} |
|
> |
|
☰ |
|
</MobileMenuButton> |
|
</NavWrapper> |
|
|
|
<MobileMenu $isOpen={isMenuOpen} ref={menuRef} data-testid="mobile-menu"> |
|
{["/", "/vardig", "/about", "/blogs", "/jobs", "/contact"].map((path, i) => ( |
|
<Link |
|
key={i} |
|
to={path} |
|
onClick={() => setIsMenuOpen(false)} // Close on click |
|
style={{ |
|
backgroundColor: location.pathname === path ? "#1d9b62" : "transparent", |
|
}} |
|
> |
|
{path === "/" |
|
? "Home" |
|
: path.replace("/", "").charAt(0).toUpperCase() + |
|
path.replace("/", "").slice(1)} |
|
</Link> |
|
))} |
|
</MobileMenu> |
|
</HeaderContainer> |
|
); |
|
}; |
|
|
|
export default Header; |