Leaflet Blog in Deno Fresh
1import { Footer } from "../components/footer.tsx"; 2import type { ComponentChildren } from "preact"; 3import { useEffect, useState } from "preact/hooks"; 4 5export function Layout({ children }: { children: ComponentChildren }) { 6 const [isScrolled, setIsScrolled] = useState(false); 7 const [blogHovered, setBlogHovered] = useState(false); 8 const [aboutHovered, setAboutHovered] = useState(false); 9 10 // Get current path to determine active nav item 11 const path = typeof window !== "undefined" ? window.location.pathname : ""; 12 const isActive = (href: string) => { 13 if (href === "/") { 14 return path === "/" || path.startsWith("/post/"); 15 } 16 return path === href; 17 }; 18 19 useEffect(() => { 20 const handleScroll = () => { 21 setIsScrolled(window.scrollY > 0); 22 }; 23 24 window.addEventListener("scroll", handleScroll); 25 handleScroll(); // Check initial scroll position 26 27 return () => window.removeEventListener("scroll", handleScroll); 28 }, []); 29 30 return ( 31 <div class="flex flex-col min-h-dvh"> 32 <nav class="w-full sticky top-0 z-50 backdrop-blur-sm transition-[padding,border-color] duration-200"> 33 <div class="relative"> 34 <div 35 class="absolute inset-x-0 bottom-0 h-2 diagonal-pattern opacity-0 transition-opacity duration-300" 36 style={{ opacity: isScrolled ? 0.25 : 0 }} 37 /> 38 <div class="max-w-screen-2xl mx-auto px-8 py-5 flex justify-between items-center"> 39 <div class="flex items-center gap-7"> 40 <a href="/" class="font-serif text-xl"> 41 knotbin 42 </a> 43 <div class="h-4 w-px bg-slate-200 dark:bg-slate-700"></div> 44 <div class="text-base flex items-center gap-7"> 45 <a 46 href="/" 47 class="relative group" 48 data-current={isActive("/")} 49 data-hovered={blogHovered} 50 onMouseEnter={() => setBlogHovered(true)} 51 onMouseLeave={() => setBlogHovered(false)} 52 > 53 <span class="opacity-50 group-hover:opacity-100 group-data-[current=true]:opacity-100 transition-opacity"> 54 blog 55 </span> 56 <div class="absolute bottom-0 left-0 w-full h-px bg-current scale-x-0 group-hover:scale-x-100 group-data-[current=true]:scale-x-100 transition-transform duration-300 ease-in-out group-hover:origin-left group-data-[hovered=false]:origin-right" /> 57 </a> 58 <a 59 href="/about" 60 class="relative group" 61 data-current={isActive("/about")} 62 data-hovered={aboutHovered} 63 onMouseEnter={() => setAboutHovered(true)} 64 onMouseLeave={() => setAboutHovered(false)} 65 > 66 <span class="opacity-50 group-hover:opacity-100 group-data-[current=true]:opacity-100 transition-opacity"> 67 about 68 </span> 69 <div class="absolute bottom-0 left-0 w-full h-px bg-current scale-x-0 group-hover:scale-x-100 group-data-[current=true]:scale-x-100 transition-transform duration-300 ease-in-out group-hover:origin-left group-data-[hovered=false]:origin-right" /> 70 </a> 71 </div> 72 </div> 73 </div> 74 </div> 75 </nav> 76 77 <main class="flex-1">{children}</main> 78 79 <Footer /> 80 </div> 81 ); 82}