Files
wr.do/components/layout/navbar.tsx
2024-07-29 15:56:35 +08:00

135 lines
4.4 KiB
TypeScript

"use client";
import { useContext } from "react";
import Link from "next/link";
import { useSelectedLayoutSegment } from "next/navigation";
import { useSession } from "next-auth/react";
import { docsConfig } from "@/config/docs";
import { marketingConfig } from "@/config/marketing";
import { siteConfig } from "@/config/site";
import { cn } from "@/lib/utils";
import { useScroll } from "@/hooks/use-scroll";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { DocsSearch } from "@/components/docs/search";
import { ModalContext } from "@/components/modals/providers";
import { Icons } from "@/components/shared/icons";
import MaxWidthWrapper from "@/components/shared/max-width-wrapper";
interface NavBarProps {
scroll?: boolean;
large?: boolean;
}
export function NavBar({ scroll = false }: NavBarProps) {
const scrolled = useScroll(50);
const { data: session, status } = useSession();
const { setShowSignInModal } = useContext(ModalContext);
const selectedLayout = useSelectedLayoutSegment();
const documentation = selectedLayout === "docs";
const configMap = {
docs: docsConfig.mainNav,
};
const links =
(selectedLayout && configMap[selectedLayout]) || marketingConfig.mainNav;
return (
<header
className={`sticky top-0 z-40 flex w-full justify-center bg-background/60 backdrop-blur-xl transition-all ${
scroll ? (scrolled ? "border-b" : "bg-transparent") : "border-b"
}`}
>
<MaxWidthWrapper
className="flex h-14 items-center justify-between py-4"
large={documentation}
>
<div className="flex gap-6 md:gap-10">
<Link href="/" className="flex items-center space-x-1.5">
<Icons.logo />
<span className="text-xl font-bold">{siteConfig.name}</span>
</Link>
{links && links.length > 0 ? (
<nav className="hidden gap-6 md:flex">
{links.map((item, index) => (
<Link
key={index}
href={item.disabled ? "#" : item.href}
prefetch={true}
className={cn(
"flex items-center text-lg font-medium transition-colors hover:text-foreground/80 sm:text-sm",
item.href.startsWith(`/${selectedLayout}`)
? "text-foreground"
: "text-foreground/60",
item.disabled && "cursor-not-allowed opacity-80",
)}
>
{item.title}
</Link>
))}
</nav>
) : null}
</div>
<div className="flex items-center space-x-3">
{/* right header for docs */}
{documentation ? (
<div className="hidden flex-1 items-center space-x-4 sm:justify-end lg:flex">
<div className="hidden lg:flex lg:grow-0">
<DocsSearch />
</div>
<div className="flex lg:hidden">
<Icons.search className="size-6 text-muted-foreground" />
</div>
<div className="flex space-x-4">
<Link
href={siteConfig.links.github}
target="_blank"
rel="noreferrer"
>
<Icons.gitHub className="size-7" />
<span className="sr-only">GitHub</span>
</Link>
</div>
</div>
) : null}
{session ? (
<Link
href={session.user.role === "ADMIN" ? "/admin" : "/dashboard"}
className="hidden md:block"
>
<Button
className="gap-2 px-4"
variant="default"
size="sm"
rounded="xl"
>
<span>Dashboard</span>
</Button>
</Link>
) : status === "unauthenticated" ? (
<Link href="login">
<Button
className="hidden gap-2 px-4 md:flex"
variant="default"
size="sm"
rounded="lg"
>
<span>Sign in</span>
<Icons.arrowRight className="size-4" />
</Button>
</Link>
) : (
<Skeleton className="hidden h-9 w-24 rounded-xl lg:flex" />
)}
</div>
</MaxWidthWrapper>
</header>
);
}