Files
reui-blocks/blocks/navbar18.tsx
T

296 lines
9.5 KiB
TypeScript

"use client";
import { Menu } from "lucide-react";
import React from "react";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
const NAV_LOGO = {
url: "https://www.ShadcnBlocks",
src: "/block-media/shadcnblocks/block/logos/ShadcnBlockscom-icon.svg",
alt: "لوگو",
title: "وندوک",
};
const NAV_ITEMS = [
{
name: "محصولات",
link: "/",
hasSubmenu: true,
submenu: [
{
title: "معرفی",
href: "/docs",
description:
"ماژول‌های آماده سامانه مدیریت ارتباط با مشتری برای مخاطبین، فرصت‌ها و گزارش فروش.",
},
{
title: "راه‌اندازی",
href: "/docs/installation",
description: "نحوه ساخت فضای کاری و دعوت اعضای تیم فروش.",
},
{
title: "فیلدهای سفارشی",
href: "/docs/primitives/typography",
description: "تعریف فیلدها، برچسب‌ها و مراحل قیف فروش.",
},
],
},
{
name: "منابع",
link: "/",
hasSubmenu: true,
submenu: [
{
title: "هشدار فرصت",
href: "/docs/primitives/alert-dialog",
description:
"هشدار ازدست‌رفتن معامله و اقدام پیشنهادی برای نماینده.",
},
{
title: "کارت مخاطب",
href: "/docs/primitives/hover-card",
description: "پیش‌نمایش سریع مخاطب، شرکت و فعالیت‌های اخیر.",
},
{
title: "پیشرفت معامله",
href: "/docs/primitives/progress",
description: "نمایش مرحله فعلی فرصت در قیف فروش.",
},
{
title: "فهرست فعالیت",
href: "/docs/primitives/scroll-area",
description: "مرور تایم‌لاین تماس‌ها، ایمیل‌ها و یادداشت‌ها.",
},
{
title: "نمای‌های فروش",
href: "/docs/primitives/tabs",
description: "جابه‌جایی بین لیست، کانبان و پیش‌بینی.",
},
{
title: "راهنمای زمینه",
href: "/docs/primitives/tooltip",
description:
"توضیح متریک‌ها و فیلدها در لحظه استفاده.",
},
],
},
{ name: "یکپارچه‌سازی", link: "/" },
];
interface Navbar18Props {
className?: string;
}
const Navbar18 = ({ className }: Navbar18Props) => {
return (
<section
lang="fa"
className={cn(
"relative z-10 mx-auto flex max-w-full items-center justify-between overflow-visible border border-t-0 bg-muted px-6 py-3 text-start md:w-fit md:rounded-b-2xl lg:gap-4",
className,
)}
>
<a href={NAV_LOGO.url} className="flex items-center gap-1">
<img
src={NAV_LOGO.src}
className="max-h-5 dark:invert"
alt={NAV_LOGO.alt}
/>
<span className="sr-only">{NAV_LOGO.title}</span>
</a>
<MobileNav />
<NavigationMenu
className="relative z-50 hidden md:flex"
dir="rtl"
viewport={false}
>
<NavigationMenuList className="h-full w-full">
{NAV_ITEMS.map((item) =>
item.hasSubmenu ? (
<NavigationMenuItem key={item.name} className="rounded-2xl">
<NavigationMenuTrigger className="bg-transparent px-2 py-1 text-start text-xs [&_svg]:ms-1 [&_svg]:!me-0 [&_svg]:!ml-0">
{item.name}
</NavigationMenuTrigger>
<NavigationMenuContent
dir="rtl"
className="start-0 end-auto left-auto z-50 rounded-2xl text-start"
>
<ul
dir="rtl"
className={cn(
"grid w-full gap-2 p-2 text-start",
(item.submenu?.length ?? 0) > 3
? "w-[300px] md:w-[350px] md:grid-cols-2 lg:w-[400px]"
: "md:w-[150px] lg:w-[200px]",
)}
>
{item.submenu?.map((sub) => (
<ListItem
key={sub.title}
title={sub.title}
href={sub.href}
>
{sub.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
) : (
<NavigationMenuItem key={item.name}>
<NavigationMenuLink
href={item.link}
className={cn(
navigationMenuTriggerStyle(),
"bg-transparent px-3 py-1.5 text-start text-xs",
)}
>
{item.name}
</NavigationMenuLink>
</NavigationMenuItem>
),
)}
</NavigationMenuList>
</NavigationMenu>
<div className="hidden md:block">
<Button
variant="outline"
className="h-auto rounded-lg px-3 py-1.5 text-xs"
>
ورود
</Button>
</div>
</section>
);
};
const ListItem = React.forwardRef<
React.ElementRef<"a">,
React.ComponentPropsWithoutRef<"a">
>(({ className, title, children, ...props }, ref) => {
return (
<li>
<NavigationMenuLink asChild>
<a
ref={ref}
className={cn(
"flex w-full flex-col items-start gap-1 rounded-md p-2 text-start text-xs leading-none no-underline transition-colors outline-none select-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
className,
)}
{...props}
>
<div className="w-full text-start text-xs leading-none font-medium">
{title}
</div>
<p className="w-full text-start text-xs leading-snug text-muted-foreground">
{children}
</p>
</a>
</NavigationMenuLink>
</li>
);
});
ListItem.displayName = "ListItem";
const MobileNav = () => {
return (
<div className="me-2 flex items-center justify-center md:hidden">
<Popover>
<PopoverTrigger asChild>
<button
type="button"
className="flex size-8 items-center justify-center rounded-md text-foreground hover:bg-accent"
aria-label="باز کردن منو"
>
<Menu className="size-5" />
</button>
</PopoverTrigger>
<PopoverContent
dir="rtl"
align="start"
sideOffset={8}
className="z-50 w-screen max-w-xs overflow-visible p-0 text-start"
>
<div className="w-full bg-card/80 pt-2 text-start text-foreground backdrop-blur-md">
<Accordion type="single" collapsible className="w-full text-start">
{NAV_ITEMS.map((navItem) =>
navItem.hasSubmenu ? (
<AccordionItem
key={navItem.name}
value={navItem.name}
className="border-b-0"
>
<AccordionTrigger className="justify-start px-4 py-3 text-start text-xs hover:bg-accent hover:no-underline [&>svg]:ms-auto [&>svg]:me-0">
<span className="text-foreground">{navItem.name}</span>
</AccordionTrigger>
<AccordionContent className="rounded-2xl text-start">
<div className="ms-4 border-s-2 border-muted ps-2">
<ul className="py-1 text-start">
{navItem.submenu?.map((sub) => (
<li
key={sub.title}
className="px-2 py-2 text-xs hover:bg-accent"
>
<a
href={sub.href}
className="block w-full text-start"
>
{sub.title}
</a>
</li>
))}
</ul>
</div>
</AccordionContent>
</AccordionItem>
) : (
<div
key={navItem.name}
className="rounded-lg px-4 py-3 text-start text-xs hover:bg-accent"
>
<a href={navItem.link} className="block w-full text-start">
<span className="text-foreground">{navItem.name}</span>
</a>
</div>
),
)}
</Accordion>
<div className="flex flex-col gap-2 py-2">
<Button variant="secondary" className="px-3 text-xs">
ورود
</Button>
</div>
</div>
</PopoverContent>
</Popover>
</div>
);
};
export { Navbar18 };