"use client" import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle } from "@/components/ui/navigation-menu"; import { ChevronDown, Ellipsis, Menu } from "lucide-react"; import Link from "next/link"; import { useEffect, useLayoutEffect, useRef, useState } from "react"; import { Button } from "../ui/button"; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "../ui/sheet"; const links = [ { type: "link" as const, href: "/", label: "Home" }, { type: "link" as const, href: "/artworks", label: "Portfolio" }, { type: "dropdown" as const, label: "Categories", items: [ { href: "/artworks/animalstudies", label: "Animal Studies" }, // { href: "/artworks/artfight", label: "Artfight" } ], }, // { type: "link" as const, href: "/miniatures", label: "Miniatures" }, { type: "link" as const, href: "/commissions", label: "Commissions" }, { type: "link" as const, href: "/commissions/status", label: "Commission Status" }, { type: "link" as const, href: "/tos", label: "Terms of Service" }, { type: "link" as const, href: "/about", label: "About Me" }, ] export default function TopNav() { const [open, setOpen] = useState(false) const requiredLinks = [ links[0], // Home links[1], // Portfolio links[4], // Commissions ]; const flexibleLinks = links.filter((link) => !requiredLinks.includes(link)); const [visibleCount, setVisibleCount] = useState(flexibleLinks.length); const listRef = useRef(null); const containerRef = useRef(null); const measureListRef = useRef(null); const [containerWidth, setContainerWidth] = useState(0); const visibleLinks = [...requiredLinks, ...flexibleLinks.slice(0, visibleCount)]; const overflowLinks = flexibleLinks.slice(visibleCount); const showMore = overflowLinks.length > 0; useEffect(() => { const containerEl = containerRef.current; if (!containerEl) return; const update = () => { setContainerWidth(containerEl.getBoundingClientRect().width); }; const ro = new ResizeObserver(update); ro.observe(containerEl); window.addEventListener("resize", update); update(); return () => { ro.disconnect(); window.removeEventListener("resize", update); }; }, []); useLayoutEffect(() => { const measureEl = measureListRef.current; if (!measureEl || !containerWidth) return; const items = Array.from(measureEl.children) as HTMLElement[]; if (!items.length) return; const moreItem = items[items.length - 1]; const moreWidth = moreItem.getBoundingClientRect().width; const itemWidths = items.slice(0, -1).map((el) => el.getBoundingClientRect().width); const requiredIndexes = new Set([0, 1, 4]); let requiredWidth = 0; const flexibleWidths: number[] = []; itemWidths.forEach((w, idx) => { if (requiredIndexes.has(idx)) { requiredWidth += w; } else { flexibleWidths.push(w); } }); const totalFlexibleWidth = flexibleWidths.reduce((a, b) => a + b, 0); let nextVisibleCount = flexibleLinks.length; const safetyPadding = 24; if (requiredWidth + totalFlexibleWidth + safetyPadding > containerWidth) { let available = containerWidth - requiredWidth - moreWidth - safetyPadding; if (available < 0) available = 0; let fit = 0; let used = 0; for (const w of flexibleWidths) { if (used + w > available) break; used += w; fit += 1; } nextVisibleCount = fit; } if (nextVisibleCount !== visibleCount) { setVisibleCount(nextVisibleCount); } }, [containerWidth, flexibleLinks.length, visibleCount]); return (
{/* Desktop Nav */}
{visibleLinks.map((item) => { if (item.type === "dropdown") { return ( {item.label}
    {item.items.map(({ href, label }) => (
  • {label}
  • ))}
); } return ( {item.label} ); })} {showMore ? (
    {overflowLinks.map((item) => { if (item.type === "dropdown") { return (
  • {item.label}
      {item.items.map(({ href, label }) => (
    • {label}
    • ))}
  • ); } return (
  • {item.label}
  • ); })}
) : null}
{links.map((item) => (
{item.type === "dropdown" ? ( {item.label} ) : ( item.label )}
))}
Navigation
); }