Files
computer-repair/src/app/components/Navbar.js
T
asownerytandClaude Opus 5.5 275bce3b87 Phase 6: QA fixes for Lighthouse and navigation
- Map is a titled iframe (accessibility); drop @next/third-parties
- "Services" nav toggle is a real button with aria-expanded (SEO
  crawlable-anchors, accessibility)
- Hero images use default quality; page-header image is preloaded (LCP)
- Mobile services submenu no longer clips its last item

Mobile Lighthouse: / 94/100/100/100, /services/computer-repair
96/100/100/100, /areas/henderson 97/100/100/100, /contact 95/100/100/100
(performance/accessibility/best practices/SEO).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 20:52:53 +13:00

215 lines
6.8 KiB
JavaScript

"use client";
import { useState, useRef, useEffect } from "react";
import Image from "next/image";
import Link from "next/link";
import styles from "./Navbar.module.css";
import logo from "../assets/logo.svg";
import menu from "../assets/menu.svg";
import close from "../assets/close.svg";
import { usePathname } from "next/navigation";
import { ChevronDownIcon } from "lucide-react";
// import { motion } from "motion/react"
export default function Navbar() {
const pathname = usePathname();
const [isActive, setActive] = useState("false");
const [isDropdownActive, setDropdownActive] = useState(false);
function handleToggle() {
setActive(!isActive);
}
function handleDropdownToggle() {
setDropdownActive(!isDropdownActive);
}
const wrapperRef = useRef(null);
useEffect(() => {
/**
* Close the menu if clicked on outside of element
*/
function handleClickOutside(event) {
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
setActive(true);
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
return (
<nav className={`${styles.navbar} shadow-sm`}>
<div className={`${styles.container} container mx-auto`} ref={wrapperRef}>
<div className={styles.header}>
<div>
<Link href="/" className={styles.logo}>
<Image src={logo} width="32" height="32" alt="" />
<p>Te Atatu Computers</p>
</Link>
</div>
<button
className={styles.menuIcon}
aria-label="Menu"
onClick={handleToggle}
>
<Image
src={isActive ? menu : close}
width="32"
height="32"
alt=""
/>
</button>
</div>
<ul className={`${styles.links} ${isActive ? "" : styles.active}`}>
<li>
<Link
href="/"
className={`link ${pathname === "/" ? styles.active : ""}`}
>
Home
</Link>
</li>
<li
className={`
${styles.dropdown}
${isDropdownActive && !isActive ? styles.dropdownActive : ""}
`}
onMouseEnter={() => setDropdownActive(true)}
onMouseLeave={() => setDropdownActive(false)}
>
<div
data-state={isDropdownActive ? "open" : "close"}
className="flex items-center justify-center gap-1 [&[data-state=open]>svg]:rotate-180"
>
<button
type="button"
aria-expanded={isDropdownActive}
className={`${styles.dropdownTitle}
${pathname.startsWith("/services") ? styles.active : ""}`}
onClick={handleDropdownToggle}
>
Services
</button>
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
</div>
<ul className={styles.dropdownMenu}>
<li>
<Link
href="/services/computer-repair"
className={`link ${
pathname === "/services/computer-repair"
? styles.active
: ""
}`}
>
Computer & Laptop Repairs
</Link>
</li>
<li>
<Link
href="/services/computer-upgrades"
className={`link ${
pathname === "/services/computer-upgrades"
? styles.active
: ""
}`}
>
Computer Upgrades & Speedup
</Link>
</li>
<li>
<Link
href="/services/it-support"
className={`link ${
pathname === "/services/it-support" ? styles.active : ""
}`}
>
IT Support
</Link>
</li>
<li>
<Link
href="/services/virus-removal"
className={`link ${
pathname === "/services/virus-removal" ? styles.active : ""
}`}
>
Virus Removal
</Link>
</li>
<li>
<Link
href="/business"
className={`link ${
pathname === "/business" ? styles.active : ""
}`}
>
Business IT Plans
</Link>
</li>
<li>
<Link
href="/windows-10"
className={`link ${
pathname === "/windows-10" ? styles.active : ""
}`}
>
Windows 10 Help
</Link>
</li>
</ul>
</li>
<li>
<Link
href="/pricing"
className={`link ${pathname === "/pricing" ? styles.active : ""}`}
>
Pricing
</Link>
</li>
<li>
<Link
href="/about"
className={`link ${pathname === "/about" ? styles.active : ""}`}
>
About
</Link>
</li>
<li>
<Link
href="/#faq"
>
FAQ
</Link>
</li>
<li className="bg-sky-900 text-white lg:ml-4">
<Link
href="/contact"
className={`link ${pathname === "/contact" ? styles.active : ""}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M2 3.5A1.5 1.5 0 0 1 3.5 2h1.148a1.5 1.5 0 0 1 1.465 1.175l.716 3.223a1.5 1.5 0 0 1-1.052 1.767l-.933.267c-.41.117-.643.555-.48.95a11.542 11.542 0 0 0 6.254 6.254c.395.163.833-.07.95-.48l.267-.933a1.5 1.5 0 0 1 1.767-1.052l3.223.716A1.5 1.5 0 0 1 18 15.352V16.5a1.5 1.5 0 0 1-1.5 1.5H15c-1.149 0-2.263-.15-3.326-.43A13.022 13.022 0 0 1 2.43 8.326 13.019 13.019 0 0 1 2 5V3.5Z"
clipRule="evenodd"
/>
</svg>
Contact Us
</Link>
</li>
</ul>
</div>
</nav>
);
}