'use client'; import { useEffect, useMemo, useState } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { ChevronDownIcon, MenuIcon } from 'lucide-react'; import { isBrowser } from '@kit/shared/utils'; import { Button } from '@kit/ui/button'; import { Heading } from '@kit/ui/heading'; import { If } from '@kit/ui/if'; import { cn } from '@kit/ui/utils'; import type { ProcessedDocumentationPage } from '../utils/build-documentation-tree'; const DocsNavLink: React.FC<{ label: string; url: string; level: number; activePath: string; collapsible: boolean; collapsed: boolean; toggleCollapsed: () => void; }> = ({ label, url, level, activePath, collapsible, collapsed, toggleCollapsed, }) => { const isCurrent = url == activePath; const isFirstLevel = level === 0; return (
{label} {collapsible && ( )}
); }; const Node: React.FC<{ node: ProcessedDocumentationPage; level: number; activePath: string; }> = ({ node, level, activePath }) => { const [collapsed, setCollapsed] = useState(node.collapsed ?? false); const toggleCollapsed = () => setCollapsed(!collapsed); useEffect(() => { if ( activePath == node.resolvedPath || node.children.map((_) => _.resolvedPath).includes(activePath) ) { setCollapsed(false); } }, [activePath, node.children, node.resolvedPath]); return ( <> {node.children.length > 0 && !collapsed && ( )} ); }; function Tree({ tree, level, activePath, }: { tree: ProcessedDocumentationPage[]; level: number; activePath: string; }) { return (
0 ? 'border-l' : '')}> {tree.map((treeNode, index) => ( ))}
); } export default function DocsNavigation({ tree, }: { tree: ProcessedDocumentationPage[]; }) { const activePath = usePathname().replace('/docs/', ''); return ( <>
); } function getNavLinkClassName(isCurrent: boolean, isFirstLevel: boolean) { return cn( 'group flex h-8 items-center justify-between space-x-2 whitespace-nowrap rounded-md px-3 text-sm leading-none transition-colors', { [`bg-muted`]: isCurrent, [`hover:bg-muted`]: !isCurrent, [`font-semibold`]: isFirstLevel, [`font-normal`]: !isFirstLevel && isCurrent, [`hover:text-foreground-muted`]: !isFirstLevel && !isCurrent, }, ); } function FloatingDocumentationNavigation({ tree, activePath, }: React.PropsWithChildren<{ tree: ProcessedDocumentationPage[]; activePath: string; }>) { const body = useMemo(() => { return isBrowser() ? document.body : null; }, []); const [isVisible, setIsVisible] = useState(false); const enableScrolling = (element: HTMLElement) => (element.style.overflowY = ''); const disableScrolling = (element: HTMLElement) => (element.style.overflowY = 'hidden'); // enable/disable body scrolling when the docs are toggled useEffect(() => { if (!body) { return; } if (isVisible) { disableScrolling(body); } else { enableScrolling(body); } }, [isVisible, body]); // hide docs when navigating to another page useEffect(() => { setIsVisible(false); }, [activePath]); const onClick = () => { setIsVisible(!isVisible); }; return ( <>
Table of Contents
); }