SPB Git forge

spb/hilmacorp

Public
1commits 1branches 0releases
29.2 MBsize
maindefault branch
19 days agolast push
TypeScript 93.3% JavaScript 4.4% CSS 2.3%
4.4 KB · 139 lines tsx
Raw Blame History
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Hilmacorp.ai — Web Platform5 * File: components/Header.tsx6 * Description: Sticky site header with desktop navigation, mobile menu, and locale switcher (light theme)7 */89"use client";1011import { useState } from "react";12import Link from "next/link";13import { usePathname } from "next/navigation";14import Logo from "@/components/Logo";15import LocaleSwitcher from "@/components/LocaleSwitcher";1617interface NavStrings {18  home: string;19  about: string;20  founders: string;21  services: string;22  security: string;23  industries: string;24  apps: string;25  contact: string;26  cta: string;27  openMenu: string;28  closeMenu: string;29  switchLocale: string;30}3132export default function Header({33  locale,34  nav,35}: {36  locale: "fr" | "en";37  nav: NavStrings;38}) {39  const [open, setOpen] = useState(false);40  const pathname = usePathname() ?? "";4142  const links = [43    { href: `/${locale}/about`, label: nav.about },44    { href: `/${locale}/founders`, label: nav.founders },45    { href: `/${locale}/services`, label: nav.services },46    { href: `/${locale}/security`, label: nav.security },47    { href: `/${locale}/industries`, label: nav.industries },48    { href: `/${locale}/apps`, label: nav.apps },49    { href: `/${locale}/contact`, label: nav.contact },50  ];5152  return (53    <header className="sticky top-0 z-50 border-b border-line bg-paper/90 backdrop-blur-md">54      <div className="mx-auto flex h-[68px] w-full max-w-6xl items-center justify-between px-5 sm:px-8">55        <Link href={`/${locale}`} aria-label={nav.home} onClick={() => setOpen(false)}>56          <Logo />57        </Link>5859        <nav className="hidden items-center gap-1 lg:flex" aria-label="Main">60          {links.map((link) => {61            const active = pathname.startsWith(link.href);62            return (63              <Link64                key={link.href}65                href={link.href}66                className={`rounded-full px-3.5 py-1.5 text-sm transition-colors ${67                  active68                    ? "bg-accent-soft text-accent-strong"69                    : "text-ink-soft hover:text-ink"70                }`}71                aria-current={active ? "page" : undefined}72              >73                {link.label}74              </Link>75            );76          })}77        </nav>7879        <div className="hidden items-center gap-3 lg:flex">80          <LocaleSwitcher locale={locale} label={nav.switchLocale} />81          <Link82            href={`/${locale}/contact`}83            className="rounded-full bg-ink px-4.5 py-2 text-sm font-medium text-paper transition-colors hover:bg-accent-strong"84          >85            {nav.cta}86          </Link>87        </div>8889        <div className="flex items-center gap-3 lg:hidden">90          <LocaleSwitcher locale={locale} label={nav.switchLocale} />91          <button92            type="button"93            onClick={() => setOpen(!open)}94            aria-expanded={open}95            aria-label={open ? nav.closeMenu : nav.openMenu}96            className="flex h-9 w-9 items-center justify-center rounded-lg border border-line-strong text-ink"97          >98            <svg width="18" height="18" viewBox="0 0 18 18" fill="none" aria-hidden="true">99              {open ? (100                <path d="M4 4l10 10M14 4L4 14" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />101              ) : (102                <path d="M2 5h14M2 9h14M2 13h14" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />103              )}104            </svg>105          </button>106        </div>107      </div>108109      {open ? (110        <nav111          className="border-t border-line bg-paper px-5 pb-6 pt-3 lg:hidden"112          aria-label="Mobile"113        >114          <ul className="flex flex-col">115            {links.map((link) => (116              <li key={link.href}>117                <Link118                  href={link.href}119                  onClick={() => setOpen(false)}120                  className="block rounded-lg px-2 py-3 text-base text-ink-soft hover:bg-paper-2 hover:text-ink"121                >122                  {link.label}123                </Link>124              </li>125            ))}126          </ul>127          <Link128            href={`/${locale}/contact`}129            onClick={() => setOpen(false)}130            className="mt-3 block rounded-full bg-ink px-4 py-2.5 text-center text-sm font-medium text-paper"131          >132            {nav.cta}133          </Link>134        </nav>135      ) : null}136    </header>137  );138}139