"use client"; import Link from "next/link"; import { useEffect, useState } from "react"; import { SettingsDialog } from "@/components/SettingsDialog"; import { TabBar } from "@/components/TabBar"; import { ThemeToggle } from "@/components/ThemeToggle"; import { IS_DEV_INSTANCE } from "@/lib/dev-mode"; import { useI18n } from "@/lib/i18n"; import { OPEN_SETTINGS_EVENT } from "@/lib/ui-events"; import { cn } from "@/lib/utils"; /** * Minimal, sticky frosted top bar: brand on the left, theme chip on the * right. Phones navigate with the bottom tab bar (also mounted here, so every * screen that has a header gets it); the desktop rail carries navigation. */ export function AppHeader({ className, compact = false }: { className?: string; compact?: boolean }) { const { t } = useI18n(); const [settingsOpen, setSettingsOpen] = useState(false); const [settingsFocus, setSettingsFocus] = useState<{ field: "key"; nonce: number } | null>(null); useEffect(() => { const onOpen = (event: Event) => { setSettingsOpen(true); const focus = (event as CustomEvent<{ focus?: string }>).detail?.focus; if (focus === "key") setSettingsFocus({ field: "key", nonce: Date.now() }); }; window.addEventListener(OPEN_SETTINGS_EVENT, onOpen); return () => window.removeEventListener(OPEN_SETTINGS_EVENT, onOpen); }, []); // Restore the desktop sidebar width preference once, on the client. useEffect(() => { void import("@/components/Sidebar").then((module) => module.sidebarCollapse.hydrate()); }, []); return ( <> , // which has no horizontal padding — the -mx-4 made it 16px wider // than the viewport and caused a horizontal scroll on phones. "glass app-header sticky top-0 z-40 mb-6 px-4 lg:hidden sm:px-6", className, )} > {/* eslint-disable-next-line @next/next/no-img-element -- static app icon, no optimisation needed */} Freezmo {IS_DEV_INSTANCE ? ( DEV ) : null} {!compact ? ( {t("header.tagline")} ) : null} setSettingsOpen(false)} focusField={settingsFocus} /> > ); }