From 64d1d67eb69075ef483a376c8d85aec378d6b111 Mon Sep 17 00:00:00 2001 From: cupadev-admin Date: Mon, 9 Mar 2026 18:16:23 +0000 Subject: [PATCH] fix: apply designer agent improvements to src/components/public/SiteHeader.tsx --- src/components/public/SiteHeader.tsx | 263 +++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 src/components/public/SiteHeader.tsx diff --git a/src/components/public/SiteHeader.tsx b/src/components/public/SiteHeader.tsx new file mode 100644 index 0000000..aa772c5 --- /dev/null +++ b/src/components/public/SiteHeader.tsx @@ -0,0 +1,263 @@ +'use client' +import { useState, useEffect, useRef, useCallback } from 'react' +import Link from 'next/link' +import Image from 'next/image' +import { Menu, X, ChevronDown, Phone, Mail } from 'lucide-react' +import { useSettingsStore } from '@/store/settingsStore' +import { useNavigationStore } from '@/store/navigationStore' +import clsx from 'clsx' + +export default function SiteHeader() { + const { settings } = useSettingsStore() + const { items } = useNavigationStore() + const [mobileOpen, setMobileOpen] = useState(false) + const [scrolled, setScrolled] = useState(false) + const mobileMenuRef = useRef(null) + const menuButtonRef = useRef(null) + + const visibleItems = items + .filter((i) => i.isVisible && i.parentId === null) + .sort((a, b) => a.order - b.order) + + useEffect(() => { + const handleScroll = () => setScrolled(window.scrollY > 10) + window.addEventListener('scroll', handleScroll, { passive: true }) + return () => window.removeEventListener('scroll', handleScroll) + }, []) + + useEffect(() => { + if (!mobileOpen) return + const handleKey = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + setMobileOpen(false) + menuButtonRef.current?.focus() + } + } + document.addEventListener('keydown', handleKey) + return () => document.removeEventListener('keydown', handleKey) + }, [mobileOpen]) + + useEffect(() => { + settings.applyThemeVars?.() + }, [settings]) + + const closeMobile = useCallback(() => { + setMobileOpen(false) + menuButtonRef.current?.focus() + }, []) + + const headerStyle = { + backgroundColor: settings.headerBgColor, + color: settings.headerTextColor, + position: settings.headerPosition as 'sticky' | 'static' | 'fixed', + } + + return ( + <> + {/* Top Bar */} + {settings.showTopBar && settings.topBarText && ( +
+ {settings.topBarText} +
+ )} + + {/* Tricolor stripe */} +