103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
import { Fragment, useState } from "react";
|
|
import { t as i18nT } from "i18next";
|
|
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from "../sheet";
|
|
import { Button } from "../button";
|
|
import Logo from "~/components/brand/Logo";
|
|
import { ScrollArea } from "../scroll-area";
|
|
import { Link } from "react-router";
|
|
import clsx from "clsx";
|
|
import { SideBarItem } from "~/application/sidebar/SidebarItem";
|
|
import { getUiIdAttributes, UI_ACTION_IDS } from "~/application/ui/uiRegistry";
|
|
import { MenuIcon } from "~/components/ui/icons/vendor";
|
|
|
|
export function MobileNav({ items }: { items: SideBarItem[] }) {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
return (
|
|
<Sheet open={open} onOpenChange={setOpen}>
|
|
<SheetTrigger asChild>
|
|
<Button
|
|
variant="ghost"
|
|
data-ui-id={`${UI_ACTION_IDS.sidebarTrigger}.docsMobile`}
|
|
className="px-0 text-base hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 md:hidden"
|
|
>
|
|
<MenuIcon className="text-text-neutral-tertiary h-6 w-6" />
|
|
<span className="sr-only">{i18nT("components.docsMobileNav.toggleMenu")}</span>
|
|
</Button>
|
|
</SheetTrigger>
|
|
<SheetContent side="left" className="pr-0">
|
|
<SheetHeader className="sr-only">
|
|
<SheetTitle>{i18nT("docs.mobileNav.title")}</SheetTitle>
|
|
<SheetDescription>{i18nT("docs.mobileNav.description")}</SheetDescription>
|
|
</SheetHeader>
|
|
<Logo className="mr-2" />
|
|
<ScrollArea className="my-4 h-[calc(100vh-100px)] pb-10 pl-3">
|
|
<div className="flex flex-col space-y-2">
|
|
{items.map((item, index) => (
|
|
<div key={index} className="flex flex-col space-y-3 pt-4" {...(!item.path ? getUiIdAttributes(item) : {})}>
|
|
{item.items && item.items.length > 0 ? (
|
|
<button type="button" aria-expanded="true" className="text-left font-medium" {...getUiIdAttributes(item)}>
|
|
{item.title}
|
|
</button>
|
|
) : item.path ? (
|
|
<Link to={item.path} {...getUiIdAttributes(item)}>
|
|
<h4 className="font-medium">{item.title}</h4>
|
|
</Link>
|
|
) : (
|
|
<h4 className="font-medium">{item.title}</h4>
|
|
)}
|
|
{item.items?.map((item) => (
|
|
<Fragment key={item.path}>
|
|
{!item.disabled &&
|
|
(item.path ? (
|
|
<MobileLink href={item.path} onOpenChange={setOpen} className="text-text-neutral-tertiary" uiItem={item}>
|
|
{item.title}
|
|
{item.side && (
|
|
<span className="ml-2 rounded-md bg-[#adfa1d] px-1.5 py-0.5 text-xs leading-none text-[#000000] no-underline group-hover:no-underline">
|
|
{item.side}
|
|
</span>
|
|
)}
|
|
</MobileLink>
|
|
) : (
|
|
item.title
|
|
))}
|
|
</Fragment>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</ScrollArea>
|
|
</SheetContent>
|
|
</Sheet>
|
|
);
|
|
}
|
|
|
|
function MobileLink({
|
|
href,
|
|
onOpenChange,
|
|
className,
|
|
children,
|
|
uiItem,
|
|
...props
|
|
}: {
|
|
href: string;
|
|
onOpenChange: (open: boolean) => void;
|
|
className: string;
|
|
children: React.ReactNode;
|
|
uiItem?: SideBarItem;
|
|
}) {
|
|
return (
|
|
<Link
|
|
to={href}
|
|
onClick={() => {
|
|
onOpenChange?.(false);
|
|
}}
|
|
className={clsx(className)}
|
|
{...(uiItem ? getUiIdAttributes(uiItem) : {})}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</Link>
|
|
);
|
|
}
|