refactor: Migrate documentation content, rebuild UI components, and update core architecture.

This commit is contained in:
gitfromwildan
2026-03-10 01:38:58 +07:00
parent aac81dff8a
commit ab755844a3
132 changed files with 3947 additions and 12862 deletions

View File

@@ -1,87 +1,158 @@
import { ArrowUpRight } from "lucide-react";
import Link from "next/link";
import Image from "next/image";
import Search from "@/components/search";
import Anchor from "@/components/anchor";
import { SheetLeftbar } from "@/components/leftbar";
import { SheetClose } from "@/components/ui/sheet";
import { Separator } from "@/components/ui/separator";
import docuConfig from "@/docu.json"; // Import JSON
"use client"
export function Navbar() {
import { ArrowUpRight, ChevronDown, ChevronUp } from "lucide-react"
import Link from "next/link"
import Image from "next/image"
import Search from "@/components/SearchBox"
import Anchor from "@/components/anchor"
import { Separator } from "@/components/ui/separator"
import docuConfig from "@/docu.json"
import { Button } from "@/components/ui/button"
import { useState, useCallback } from "react"
import { motion, AnimatePresence } from "framer-motion"
import { ModeToggle } from "@/components/ThemeToggle"
interface NavbarProps {
id?: string
}
export function Navbar({ id }: NavbarProps) {
const [isMenuOpen, setIsMenuOpen] = useState(false)
const toggleMenu = useCallback(() => {
setIsMenuOpen((prev) => !prev)
}, [])
return (
<nav className="sticky top-0 z-50 w-full h-16 border-b bg-background">
<div className="sm:container mx-auto w-[95vw] h-full flex items-center justify-between md:gap-2">
<div className="flex items-center gap-5">
<SheetLeftbar />
<div className="sticky top-0 z-50 w-full">
<nav id={id} className="bg-background h-16 w-full border-b">
<div className="mx-auto flex h-full w-[95vw] items-center justify-between sm:container md:gap-2">
<div className="flex items-center gap-6">
<div className="hidden lg:flex">
<div className="flex">
<Logo />
</div>
</div>
</div>
<div className="flex items-center gap-2">
<div className="items-center hidden gap-4 text-sm font-medium lg:flex text-muted-foreground">
<div className="flex items-center gap-0 max-md:flex-row-reverse md:gap-2">
<div className="text-muted-foreground hidden items-center gap-4 text-sm font-medium md:flex">
<NavMenu />
</div>
<Separator className="hidden lg:flex my-4 h-9" orientation="vertical" />
<Button
variant="ghost"
size="sm"
onClick={toggleMenu}
aria-label={isMenuOpen ? "Close navigation menu" : "Open navigation menu"}
aria-expanded={isMenuOpen}
className="flex items-center gap-1 px-2 text-sm font-medium md:hidden"
>
{isMenuOpen ? (
<ChevronUp className="text-muted-foreground h-6 w-6" />
) : (
<ChevronDown className="text-muted-foreground h-6 w-6" />
)}
</Button>
<Separator className="my-4 hidden h-9 md:flex" orientation="vertical" />
<Search />
</div>
</div>
</div>
</nav>
);
</nav>
<AnimatePresence>
{isMenuOpen && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
className="bg-background/95 w-full border-b shadow-sm backdrop-blur-sm md:hidden"
>
<div className="mx-auto w-[95vw] sm:container">
<ul className="flex flex-col py-2">
<NavMenuCollapsible onItemClick={() => setIsMenuOpen(false)} />
</ul>
<div className="flex items-center justify-between border-t px-1 py-3">
<ModeToggle />
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
)
}
export function Logo() {
const { navbar } = docuConfig; // Extract navbar from JSON
const { navbar } = docuConfig
return (
<Link href="/" className="flex items-center gap-1.5">
<div className="relative w-8 h-8">
<Image
src={navbar.logo.src}
alt={navbar.logo.alt}
fill
sizes="32px"
className="object-contain"
/>
</div>
<h2 className="font-bold font-code text-md">{navbar.logoText}</h2>
</Link>
);
return (
<Link href="/" className="flex items-center gap-1.5">
<div className="relative h-8 w-8">
<Image
src={navbar.logo.src}
alt={navbar.logo.alt}
fill
sizes="32px"
className="object-contain"
/>
</div>
<h2 className="font-code dark:text-accent text-primary text-lg font-bold">
{navbar.logoText}
</h2>
</Link>
)
}
export function NavMenu({ isSheet = false }) {
const { navbar } = docuConfig; // Extract navbar from JSON
// Desktop NavMenu — horizontal list
export function NavMenu() {
const { navbar } = docuConfig
return (
<>
{navbar?.menu?.map((item) => {
const isExternal = item.href.startsWith("http");
const Comp = (
const isExternal = item.href.startsWith("http")
return (
<Anchor
key={`${item.title}-${item.href}`}
activeClassName="text-primary dark:text-accent md:font-semibold font-medium"
absolute
className="flex items-center gap-1 text-foreground/80 hover:text-foreground transition-colors"
className="text-foreground/80 hover:text-foreground flex items-center gap-1 transition-colors"
href={item.href}
target={isExternal ? "_blank" : undefined}
rel={isExternal ? "noopener noreferrer" : undefined}
>
{item.title}
{isExternal && <ArrowUpRight className="w-4 h-4 text-foreground/80" />}
{isExternal && <ArrowUpRight className="text-foreground/80 h-4 w-4" />}
</Anchor>
);
return isSheet ? (
<SheetClose key={item.title + item.href} asChild>
{Comp}
</SheetClose>
) : (
Comp
);
)
})}
</>
);
)
}
// Mobile Collapsible NavMenu — vertical list items
function NavMenuCollapsible({ onItemClick }: { onItemClick: () => void }) {
const { navbar } = docuConfig
return (
<>
{navbar?.menu?.map((item) => {
const isExternal = item.href.startsWith("http")
return (
<li key={item.title + item.href}>
<Anchor
activeClassName="text-primary dark:text-accent font-semibold"
absolute
className="text-foreground/80 hover:text-foreground hover:bg-muted flex w-full items-center justify-between gap-2 rounded-md px-3 py-2.5 text-sm font-medium transition-colors"
href={item.href}
target={isExternal ? "_blank" : undefined}
rel={isExternal ? "noopener noreferrer" : undefined}
onClick={onItemClick}
>
{item.title}
{isExternal && <ArrowUpRight className="text-foreground/60 h-4 w-4 shrink-0" />}
</Anchor>
</li>
)
})}
</>
)
}