Files
reui-blocks/blocks/navbar2.tsx
T

303 lines
9.1 KiB
TypeScript

"use client";
import { Book, Menu, Sunset, Trees, Zap } from "lucide-react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu";
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import { cn } from "@/lib/utils";
interface MenuItem {
title: string;
url: string;
description?: string;
icon?: React.ReactNode;
items?: MenuItem[];
}
interface Navbar2Props {
logo?: {
url: string;
src: string;
alt: string;
title: string;
className?: string;
};
menu?: MenuItem[];
auth?: {
login: {
title: string;
url: string;
};
signup: {
title: string;
url: string;
};
};
className?: string;
}
const Navbar2 = ({
logo = {
url: "https://www.ShadcnBlocks",
src: "/block-media/shadcnblocks/block/logos/ShadcnBlockscom-icon.svg",
alt: "لوگو",
title: "وندوک",
},
menu = [
{ title: "خانه", url: "#" },
{
title: "محصولات",
url: "#",
items: [
{
title: "وبلاگ",
description: "بینش فروش، گزارش محصول و روندهای سامانه مدیریت ارتباط با مشتری",
icon: <Book className="size-5 shrink-0" />,
url: "#",
},
{
title: "شرکت",
description: "مأموریت ما شفاف‌سازی پایپ‌لاین فروش B2B است",
icon: <Trees className="size-5 shrink-0" />,
url: "#",
},
{
title: "فرصت‌های شغلی",
description: "موقعیت‌های باز در تیم محصول و درآمد",
icon: <Sunset className="size-5 shrink-0" />,
url: "#",
},
{
title: "پشتیبانی",
description: "با تیم موفقیت مشتری صحبت کنید یا راهنما را ببینید",
icon: <Zap className="size-5 shrink-0" />,
url: "#",
},
],
},
{
title: "منابع",
url: "#",
items: [
{
title: "مرکز راهنما",
description: "راه‌اندازی سامانه مدیریت ارتباط با مشتری، واردات داده و بهترین روش‌ها",
icon: <Zap className="size-5 shrink-0" />,
url: "#",
},
{
title: "تماس با ما",
description: "برای دمو، قیمت‌گذاری و مهاجرت سامانه مدیریت ارتباط با مشتری آماده‌ایم",
icon: <Sunset className="size-5 shrink-0" />,
url: "#",
},
{
title: "وضعیت سرویس",
description: "وضعیت فعلی پلتفرم و یکپارچه‌سازی‌ها",
icon: <Trees className="size-5 shrink-0" />,
url: "#",
},
{
title: "شرایط استفاده",
description: "قوانین استفاده از وندوک",
icon: <Book className="size-5 shrink-0" />,
url: "#",
},
],
},
{ title: "قیمت‌گذاری", url: "#" },
{ title: "وبلاگ", url: "#" },
],
auth = {
login: { title: "ورود", url: "#" },
signup: { title: "شروع رایگان", url: "#" },
},
className,
}: Navbar2Props) => {
return (
<section
lang="fa"
className={cn("overflow-visible py-4 text-start", className)}
>
<div className="container">
<nav className="relative z-10 hidden justify-between overflow-visible lg:flex">
<a href={logo.url} className="flex items-center gap-2">
<img src={logo.src} className="max-h-8" alt={logo.alt} />
<span className="text-lg font-semibold tracking-tighter">
{logo.title}
</span>
</a>
<div className="flex items-center gap-6">
<NavigationMenu
dir="rtl"
viewport={false}
className="relative z-50 max-w-none overflow-visible"
>
<NavigationMenuList>
{menu.map((item) => renderMenuItem(item))}
</NavigationMenuList>
</NavigationMenu>
</div>
<div className="flex gap-2">
<Button asChild variant="outline" size="sm">
<a href={auth.login.url}>{auth.login.title}</a>
</Button>
<Button asChild size="sm">
<a href={auth.signup.url}>{auth.signup.title}</a>
</Button>
</div>
</nav>
<div className="block lg:hidden">
<div className="flex items-center justify-between">
<a href={logo.url} className="flex items-center gap-2">
<img src={logo.src} className="max-h-8" alt={logo.alt} />
</a>
<Sheet>
<SheetTrigger asChild>
<Button
variant="outline"
size="icon"
aria-label="باز کردن منو"
>
<Menu className="size-4" />
</Button>
</SheetTrigger>
<SheetContent
dir="rtl"
className="overflow-y-auto text-start"
>
<SheetHeader>
<SheetTitle>
<a href={logo.url} className="flex items-center gap-2">
<img src={logo.src} className="max-h-8" alt={logo.alt} />
</a>
</SheetTitle>
</SheetHeader>
<div className="flex flex-col gap-6 p-4">
<Accordion
type="single"
collapsible
dir="rtl"
className="flex w-full flex-col gap-4 text-start"
>
{menu.map((item) => renderMobileMenuItem(item))}
</Accordion>
<div className="flex flex-col gap-3">
<Button asChild variant="outline">
<a href={auth.login.url}>{auth.login.title}</a>
</Button>
<Button asChild>
<a href={auth.signup.url}>{auth.signup.title}</a>
</Button>
</div>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</div>
</section>
);
};
const renderMenuItem = (item: MenuItem) => {
if (item.items) {
return (
<NavigationMenuItem key={item.title} className="relative">
<NavigationMenuTrigger className="text-start [&_svg]:ms-1 [&_svg]:!me-0 [&_svg]:!ml-0">
{item.title}
</NavigationMenuTrigger>
<NavigationMenuContent
dir="rtl"
className="start-0 end-auto left-auto z-50 !w-80 max-w-[calc(100vw-2rem)] text-start"
>
{item.items.map((subItem) => (
<NavigationMenuLink asChild key={subItem.title}>
<SubMenuLink item={subItem} />
</NavigationMenuLink>
))}
</NavigationMenuContent>
</NavigationMenuItem>
);
}
return (
<NavigationMenuItem key={item.title}>
<NavigationMenuLink
href={item.url}
className="group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-start text-sm font-medium transition-colors hover:bg-muted hover:text-accent-foreground"
>
{item.title}
</NavigationMenuLink>
</NavigationMenuItem>
);
};
const renderMobileMenuItem = (item: MenuItem) => {
if (item.items) {
return (
<AccordionItem key={item.title} value={item.title} className="border-b-0">
<AccordionTrigger className="justify-start py-0 text-start text-base font-semibold hover:no-underline [&>svg]:ms-auto [&>svg]:me-0">
{item.title}
</AccordionTrigger>
<AccordionContent className="mt-2 text-start">
{item.items.map((subItem) => (
<SubMenuLink key={subItem.title} item={subItem} />
))}
</AccordionContent>
</AccordionItem>
);
}
return (
<a
key={item.title}
href={item.url}
className="block text-start text-base font-semibold"
>
{item.title}
</a>
);
};
const SubMenuLink = ({ item }: { item: MenuItem }) => {
return (
<a
className="flex w-full flex-row gap-4 rounded-md p-3 text-start leading-none no-underline transition-colors outline-none select-none hover:bg-muted hover:text-accent-foreground"
href={item.url}
>
<div className="shrink-0 text-muted-foreground">{item.icon}</div>
<div className="min-w-0">
<div className="text-sm font-semibold">{item.title}</div>
{item.description && (
<p className="text-sm leading-snug text-muted-foreground">
{item.description}
</p>
)}
</div>
</a>
);
};
export { Navbar2 };