"use client" import Link from "next/link" import { usePathname } from "next/navigation" import { PAGES_NEW } from "@/lib/docs" import { showMcpDocs } from "@/lib/flags" import type { source } from "@/lib/source" import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from "@/registry/new-york-v4/ui/sidebar" type PageTreeNode = (typeof source.pageTree)["children"][number] type PageTreeFolder = Extract type PageTreePage = Extract const TOP_LEVEL_SECTIONS = [ { name: "Get Started", href: "/docs" }, { name: "Components", href: "/docs/components", }, { name: "Directory", href: "/docs/directory", }, { name: "MCP Server", href: "/docs/mcp", }, { name: "Forms", href: "/docs/forms", }, { name: "Changelog", href: "/docs/changelog", }, ] const EXCLUDED_SECTIONS = ["installation", "dark-mode"] const EXCLUDED_PAGES = ["/docs", "/docs/changelog"] // Recursively find all pages in a folder tree. function getAllPagesFromFolder(folder: PageTreeFolder): PageTreePage[] { const pages: PageTreePage[] = [] for (const child of folder.children) { if (child.type === "page") { pages.push(child) } else if (child.type === "folder") { pages.push(...getAllPagesFromFolder(child)) } } return pages } // Get the pages from a folder, handling nested base folders (radix/base). function getPagesFromFolder( folder: PageTreeFolder, currentBase: string ): PageTreePage[] { // For the components folder, find the base subfolder. if (folder.$id === "components" || folder.name === "Components") { for (const child of folder.children) { if (child.type === "folder") { // Match by $id or by name. const isRadix = child.$id === "radix" || child.name === "Radix UI" const isBase = child.$id === "base" || child.name === "Base UI" if ( (currentBase === "radix" && isRadix) || (currentBase === "base" && isBase) ) { return child.children.filter( (c): c is PageTreePage => c.type === "page" ) } } } // Fallback: return all pages from nested folders. return getAllPagesFromFolder(folder).filter( (page) => !page.url.endsWith("/components") ) } // For other folders, return direct page children. return folder.children.filter( (child): child is PageTreePage => child.type === "page" ) } export function DocsSidebar({ tree, ...props }: React.ComponentProps & { tree: typeof source.pageTree }) { const pathname = usePathname() // Detect current base from URL (radix or base). const baseMatch = pathname.match(/\/docs\/components\/(radix|base)\//) const currentBase = baseMatch ? baseMatch[1] : "radix" // Default to radix. return (
Sections {TOP_LEVEL_SECTIONS.map(({ name, href }) => { if (!showMcpDocs && href.includes("/mcp")) { return null } return ( {name} ) })} {tree.children.map((item) => { if (EXCLUDED_SECTIONS.includes(item.$id ?? "")) { return null } return ( {item.name} {item.type === "folder" && ( {getPagesFromFolder(item, currentBase).map((page) => { if (!showMcpDocs && page.url.includes("/mcp")) { return null } if (EXCLUDED_PAGES.includes(page.url)) { return null } return ( {page.name} {PAGES_NEW.includes(page.url) && ( )} ) })} )} ) })}
) }