Spaces:
Configuration error
Configuration error
| "use client" | |
| import Link from "next/link" | |
| import { usePathname } from "next/navigation" | |
| import { Suspense } from "react" | |
| import { Sparkles, Menu, X, Plus, Loader2 } from "lucide-react" | |
| import { Button } from "@/components/ui/button" | |
| import { ThemeToggle } from "@/components/ui/theme-toggle" | |
| import { UserButton } from "@/components/auth/user-button" | |
| import { NotificationBell } from "@/components/notifications/notification-center" | |
| import { OllamaSettingsModal } from "@/components/ollama/ollama-settings" | |
| import { useState } from "react" | |
| import { cn } from "@/lib/utils" | |
| const navLinks = [ | |
| { href: "/explore", label: "Explore" }, | |
| { href: "/tools", label: "Tools" }, | |
| { href: "/thunderdome", label: "Thunderdome" }, | |
| { href: "/workflows", label: "Workflows" }, | |
| { href: "/frameworks", label: "Frameworks" }, | |
| { href: "/performance", label: "Performance" }, | |
| { href: "/dashboard", label: "Dashboard" }, | |
| ] | |
| // Loading fallback for UserButton | |
| function UserButtonFallback() { | |
| return ( | |
| <div className="h-9 w-24 rounded-lg bg-muted animate-pulse flex items-center justify-center"> | |
| <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" /> | |
| </div> | |
| ) | |
| } | |
| export function Header() { | |
| const pathname = usePathname() | |
| const [mobileMenuOpen, setMobileMenuOpen] = useState(false) | |
| return ( | |
| <header className="sticky top-0 z-50 w-full border-b border-border glass-strong"> | |
| <div className="container mx-auto px-4"> | |
| <nav className="flex h-16 items-center justify-between"> | |
| {/* Logo */} | |
| <Link href="/" className="flex items-center gap-2 group"> | |
| <div className="relative h-9 w-9 overflow-hidden rounded-lg shadow-lg group-hover:shadow-primary/25 transition-shadow"> | |
| <img | |
| src="/logos/logo.svg" | |
| alt="OpenPrompt Logo" | |
| className="h-full w-full object-cover" | |
| /> | |
| </div> | |
| <span className="font-semibold text-lg tracking-tight hidden sm:block"> | |
| Open<span className="text-primary">Prompt</span> | |
| </span> | |
| </Link> | |
| {/* Desktop Navigation */} | |
| <div className="hidden md:flex items-center gap-1"> | |
| {navLinks.map((link) => { | |
| const isActive = pathname === link.href || pathname?.startsWith(`${link.href}/`) | |
| return ( | |
| <Link | |
| key={link.href} | |
| href={link.href} | |
| className={cn( | |
| "px-4 py-2 text-sm font-medium transition-colors rounded-lg", | |
| isActive | |
| ? "text-foreground bg-muted font-semibold" | |
| : "text-muted-foreground hover:text-foreground hover:bg-muted" | |
| )} | |
| > | |
| {link.label} | |
| </Link> | |
| ) | |
| })} | |
| </div> | |
| {/* Right Side Actions */} | |
| <div className="flex items-center gap-2"> | |
| <OllamaSettingsModal /> | |
| <NotificationBell /> | |
| <ThemeToggle /> | |
| <Link href="/create" className="hidden sm:flex"> | |
| <Button size="sm" className="gap-2"> | |
| <Plus className="h-4 w-4" /> | |
| Create | |
| </Button> | |
| </Link> | |
| {/* User Button with Suspense boundary */} | |
| <div className="hidden md:flex"> | |
| <Suspense fallback={<UserButtonFallback />}> | |
| <UserButton /> | |
| </Suspense> | |
| </div> | |
| {/* Mobile Menu Button */} | |
| <button | |
| onClick={() => setMobileMenuOpen(!mobileMenuOpen)} | |
| className="md:hidden h-9 w-9 rounded-lg border border-border bg-background flex items-center justify-center hover:bg-muted transition-colors" | |
| aria-label="Toggle menu" | |
| > | |
| {mobileMenuOpen ? ( | |
| <X className="h-4 w-4" /> | |
| ) : ( | |
| <Menu className="h-4 w-4" /> | |
| )} | |
| </button> | |
| </div> | |
| </nav> | |
| {/* Mobile Menu */} | |
| <div | |
| className={cn( | |
| "md:hidden overflow-hidden transition-all duration-300", | |
| mobileMenuOpen ? "max-h-96 pb-4" : "max-h-0" | |
| )} | |
| > | |
| <div className="flex flex-col gap-2 pt-2"> | |
| {navLinks.map((link) => ( | |
| <Link | |
| key={link.href} | |
| href={link.href} | |
| className="px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors rounded-lg hover:bg-muted" | |
| onClick={() => setMobileMenuOpen(false)} | |
| > | |
| {link.label} | |
| </Link> | |
| ))} | |
| <div className="flex gap-2 pt-2 border-t border-border mt-2"> | |
| <Link href="/create" className="flex-1"> | |
| <Button size="sm" className="w-full gap-2"> | |
| <Plus className="h-4 w-4" /> | |
| Create | |
| </Button> | |
| </Link> | |
| </div> | |
| {/* Mobile User Button with Suspense */} | |
| <div className="pt-2"> | |
| <Suspense fallback={<UserButtonFallback />}> | |
| <UserButton /> | |
| </Suspense> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </header> | |
| ) | |
| } | |