Files
2ec43285-3fb0-448d-8aad-fa2…/src/components/navbar/NavbarLayoutFloatingInline.tsx
2026-03-12 00:42:58 +00:00

112 lines
3.3 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import Button from "../button/Button";
import ButtonTextUnderline from "../button/ButtonTextUnderline";
import Logo from "./Logo";
import { NavItem } from "@/types/navigation";
import { cls } from "@/lib/utils";
import { getButtonProps } from "@/lib/buttonUtils";
import { useTheme } from "@/providers/themeProvider/ThemeProvider";
import type { ButtonConfig } from "@/types/button";
interface NavbarLayoutFloatingInlineProps {
navItems: NavItem[];
brandName?: string;
button: ButtonConfig;
animateOnLoad?: boolean;
className?: string;
navItemClassName?: string;
buttonClassName?: string;
buttonTextClassName?: string;
}
const NavbarLayoutFloatingInline = ({
navItems,
brandName = "Webild",
button,
animateOnLoad = true,
className = "",
navItemClassName = "",
buttonClassName = "",
buttonTextClassName = "",
}: NavbarLayoutFloatingInlineProps) => {
const theme = useTheme();
const [entered, setEntered] = useState(!animateOnLoad);
const [expanded, setExpanded] = useState(!animateOnLoad);
const [showLinks, setShowLinks] = useState(!animateOnLoad);
useEffect(() => {
if (!animateOnLoad) return;
const t1 = setTimeout(() => setEntered(true), 50);
const t2 = setTimeout(() => setExpanded(true), 1000);
const t3 = setTimeout(() => setShowLinks(true), 1900);
return () => {
clearTimeout(t1);
clearTimeout(t2);
clearTimeout(t3);
};
}, [animateOnLoad]);
return (
<nav
role="navigation"
aria-label="Main navigation"
className="fixed z-[100] top-6 w-full"
style={animateOnLoad ? {
transform: entered ? "translateY(0)" : "translateY(calc(-100% - 3rem))",
transition: "transform 900ms cubic-bezier(0.25, 0.46, 0.45, 0.94)",
} : undefined}
>
<div
className={cls(
"mx-auto flex items-center justify-between",
"card rounded-theme",
"p-3 pl-6 h-fit relative",
!animateOnLoad && "w-content-width",
className
)}
style={animateOnLoad ? {
maxWidth: expanded ? "var(--width-content-width)" : "22rem",
transition: "max-width 1000ms cubic-bezier(0.4, 0, 0.2, 1)",
} : undefined}
>
<Logo brandName={brandName} href="/" />
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 hidden md:flex gap-6 items-center">
{navItems.map((item, index) => (
<div
key={index}
className={animateOnLoad ? cls(
"transition-all duration-700 ease-out",
showLinks ? "opacity-100 translate-y-0" : "opacity-0 translate-y-3"
) : undefined}
style={animateOnLoad ? { transitionDelay: `${index * 120}ms` } : undefined}
>
<ButtonTextUnderline
text={item.name}
href={item.id}
className={cls("!text-base", navItemClassName)}
/>
</div>
))}
</div>
<Button
{...getButtonProps(
button,
0,
theme.defaultButtonVariant,
buttonClassName,
buttonTextClassName
)}
/>
</div>
</nav>
);
};
export default NavbarLayoutFloatingInline;