src/components/navbar/index.tsx'use client'import Link from 'next/link'import clsx from 'clsx'import { useEffect, useState, type ReactElement } from 'react'import { useInView } from 'react-intersection-observer'import { Logo } from '@/components/logo'import { Icon } from '@/components/icon'import { Search } from '@/components/search'import { DesktopNav } from './desktop-nav'import { MobileNavButton } from './mobile-nav-button'import type { NavbarProps, ContactItem } from './types'import { homeLink, quoteLink, quoteLabel, contactItems } from './config'import { company } from '@/config'import searchIcon from '@iconify/icons-lucide/search'/*** Main site header:* - An angled logo panel + utility strip (location, phone, email, hours) make* up the top row* - The Forge Navy nav bar sits outside that row, narrower, and overlaps it* slightly for a layered, industrial look** When `hero` is set (hero-layout pages), the whole header floats as an* overlay so the hero section sits behind it (and bleeds to the top); a fixed* copy of the navy bar slides in once the header scrolls away. On all other* pages the header is in normal flow and the navy bar stays `position: sticky`.*/export function Navbar({ hero = false }: NavbarProps = {}): ReactElement {const [isSearching, setIsSearching] = useState(false)// Sentinel sits just below the in-flow bar; once it scrolls out of view the// hero layout's fixed copy of the bar slides in.const { ref: sentinelRef, inView: navAtTop } = useInView({initialInView: true,})// Cmd/Ctrl + K opens the search dialog.useEffect(() => {if (isSearching) {return}function onKeyDown(event: KeyboardEvent) {if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {event.preventDefault()setIsSearching(true)}}window.addEventListener('keydown', onKeyDown)return () => {window.removeEventListener('keydown', onKeyDown)}}, [isSearching])// Dark charcoal nav bar contents, reused by the in-flow/overlay bar and (in// hero layout) by the fixed bar that slides in on scroll.const barInner = (<div className="flex items-stretch rounded-sm bg-accent2 shadow-xl"><DesktopNav className="pl-6" /><div className="ml-auto flex items-stretch"><buttontype="button"aria-label="Search"onClick={() => setIsSearching(true)}className="flex cursor-pointer items-center px-5 text-accent-contrast transition-colors duration-200 hover:text-accent focus:outline-none focus:ring-0"><Iconicon={searchIcon}className="h-6 w-6"/></button><Linkhref={quoteLink}className="flex items-center rounded-r-sm bg-accent-dark px-8 font-body text-base font-medium tracking-wide text-accent-contrast transition-colors duration-200 hover:bg-accent-dark/80">{quoteLabel}</Link></div></div>)return (<>{/* Mobile bar */}<divclassName={clsx('z-50 flex items-center justify-between bg-body px-6 py-4 shadow-md lg:hidden',hero ? 'fixed inset-x-0 top-0' : 'sticky top-0')}><Linkhref={homeLink}title={company.name}className="block outline-none focus:outline-none"><Logo height={48} /></Link><div className="flex items-center"><buttontype="button"aria-label="Search"onClick={() => setIsSearching(true)}className="cursor-pointer p-3 text-accent transition-colors duration-200 hover:text-accent-dark focus:outline-none"><Iconicon={searchIcon}className="h-7 w-7"/></button><MobileNavButton /></div></div>{/* Desktop header */}<divclassName={clsx('z-40 hidden px-3 lg:block',hero ? 'absolute inset-x-0 top-0' : 'relative')}>{/* Top row: red angled logo panel + white contact strip */}<headerid="navbar"className={clsx('mx-auto max-w-[1580px]',hero? 'overflow-hidden rounded-b-sm bg-body shadow-xl max-[1369px]:rounded-none': 'bg-body')}>{/* Inner row constrained to the shared content width so the logo andcontact content line up with the blue bar / page content. */}<div className="px-6 lg:px-8"><div className="mx-auto flex max-w-content items-stretch">{/* Angled logo panel */}<Linkhref={homeLink}title={company.name}className="relative z-20 -mr-10 flex items-center pt-6 pr-32 pb-9 [clip-path:polygon(0_0,100%_0,82%_100%,0_100%)]"><Logo height={64} /></Link>{/* Contact strip */}<div className="flex flex-1 items-center justify-end gap-8 pt-5 pr-0 pb-8 pl-8 xl:gap-12">{contactItems.map((item: ContactItem) => (<akey={item.title}href={item.href}{...(item.external && {target: '_blank',rel: 'noopener noreferrer',})}className="ft-tracking group flex items-center gap-3 text-contrast focus:outline-none focus:ring-0"><span className="flex size-10 flex-none items-center justify-center rounded-full text-accent ring-1 ring-body-dark transition-colors duration-200 group-hover:bg-accent group-hover:text-accent-contrast group-hover:ring-accent"><Iconicon={item.icon}className="h-4 w-4"/></span><span className="flex flex-col leading-tight"><span className="font-body text-sm font-medium tracking-wide">{item.title}</span><span className="text-xs font-normal text-contrast-light transition-colors duration-200 group-hover:text-accent">{item.value}</span></span></a>))}</div></div></div></header>{/* Hero layout: the blue bar overlays the header, and being absolute itadds no flow, so the hero image bleeds to the very top. A sentineljust beneath drives the fixed bar once the header scrolls away. */}{hero && (<><div className="relative z-40 -mt-3"><div className="mx-auto max-w-content">{barInner}</div></div><divref={sentinelRef}className="h-px w-full"/></>)}</div>{/* Non-hero: the bar is a page-level sticky sibling, so its parent is thepage, so it stays stuck for the full scroll. */}{!hero && (<div className="sticky top-0 z-40 -mt-3 hidden px-3 lg:block"><div className="mx-auto max-w-content">{barInner}</div></div>)}{/* Hero: a fixed copy of the bar slides down once the header is scrolledpast (the original overlay bar scrolls away with the header). */}{hero && (<divclassName={clsx('fixed inset-x-0 top-0 z-50 hidden px-3 transition-transform duration-300 lg:block',navAtTop ? '-translate-y-full' : 'translate-y-0')}><div className="[&>div>div]:rounded-t-none"><div className="mx-auto max-w-content">{barInner}</div></div></div>)}<SearchisOpen={isSearching}setIsOpen={setIsSearching}/></>)}