Files

162 lines
5.2 KiB
TypeScript

"use client"
import * as React from "react"
import Link, { LinkProps } from "next/link"
import { useRouter } from "next/navigation"
import { docsConfig } from "@/config/docs"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/default/ui/button"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/default/ui/popover"
const TOP_LEVEL_SECTIONS = [
{ name: "Get Started", href: "/docs" },
{ name: "Components", href: "/docs/components" },
{ name: "Blocks", href: "/blocks" },
{ name: "Themes", href: "/themes" },
{ name: "Examples", href: "/examples" },
]
export function MobileNav() {
const [open, setOpen] = React.useState(false)
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="ghost"
className={cn(
"mr-2 h-8 touch-manipulation items-center justify-start gap-2.5 !p-0 hover:bg-transparent focus-visible:bg-transparent focus-visible:ring-0 active:bg-transparent dark:hover:bg-transparent md:hidden"
)}
>
<div className="relative flex h-8 w-4 items-center justify-center">
<div className="relative size-4">
<span
className={cn(
"bg-foreground absolute left-0 block h-0.5 w-4 transition-all duration-100",
open ? "top-[0.4rem] -rotate-45" : "top-1"
)}
/>
<span
className={cn(
"bg-foreground absolute left-0 block h-0.5 w-4 transition-all duration-100",
open ? "top-[0.4rem] rotate-45" : "top-2.5"
)}
/>
</div>
<span className="sr-only">Toggle Menu</span>
</div>
<span className="flex h-8 items-center text-lg leading-none font-medium">
Menu
</span>
</Button>
</PopoverTrigger>
<PopoverContent
className="bg-background/90 no-scrollbar h-[var(--radix-popper-available-height)] w-[var(--radix-popper-available-width)] overflow-y-auto rounded-none border-none p-0 shadow-none backdrop-blur duration-100"
align="start"
side="bottom"
alignOffset={-16}
sideOffset={14}
>
<div className="flex flex-col gap-12 overflow-auto px-6 py-6">
<div className="flex flex-col gap-4">
<div className="text-muted-foreground text-sm font-medium">
Menu
</div>
<div className="flex flex-col gap-3">
<MobileLink href="/" onOpenChange={setOpen}>
Home
</MobileLink>
{docsConfig.mainNav?.map(
(item) =>
item.href && (
<MobileLink
key={item.href}
href={item.href}
onOpenChange={setOpen}
>
{item.title}
</MobileLink>
)
)}
</div>
</div>
<div className="flex flex-col gap-4">
<div className="text-muted-foreground text-sm font-medium">
Sections
</div>
<div className="flex flex-col gap-3">
{TOP_LEVEL_SECTIONS.map(({ name, href }) => (
<MobileLink key={name} href={href} onOpenChange={setOpen}>
{name}
</MobileLink>
))}
</div>
</div>
<div className="flex flex-col gap-8">
{docsConfig.sidebarNav.map((group, index) => (
<div key={index} className="flex flex-col gap-4">
<div className="text-muted-foreground text-sm font-medium">
{group.title}
</div>
<div className="flex flex-col gap-3">
{group.items?.map((item) => {
if (!item.disabled && item.href) {
return (
<MobileLink
key={item.href}
href={item.href}
onOpenChange={setOpen}
className="flex items-center gap-2"
>
{item.title}
{item.label && (
<span className="rounded-md bg-[#1447e6] px-1.5 py-0.5 text-xs leading-none text-white no-underline">
{item.label}
</span>
)}
</MobileLink>
)
}
})}
</div>
</div>
))}
</div>
</div>
</PopoverContent>
</Popover>
)
}
function MobileLink({
href,
onOpenChange,
className,
children,
...props
}: LinkProps & {
onOpenChange?: (open: boolean) => void
children: React.ReactNode
className?: string
}) {
const router = useRouter()
return (
<Link
href={href}
onClick={() => {
router.push(href.toString())
onOpenChange?.(false)
}}
className={cn("text-2xl font-medium", className)}
{...props}
>
{children}
</Link>
)
}