Version 3 of the kit: - Radix UI replaced with Base UI (using the Shadcn UI patterns) - next-intl replaces react-i18next - enhanceAction deprecated; usage moved to next-safe-action - main layout now wrapped with [locale] path segment - Teams only mode - Layout updates - Zod v4 - Next.js 16.2 - Typescript 6 - All other dependencies updated - Removed deprecated Edge CSRF - Dynamic Github Action runner
150 lines
3.0 KiB
TypeScript
150 lines
3.0 KiB
TypeScript
import { ChevronDown } from 'lucide-react';
|
|
|
|
import { Cms } from '@kit/cms';
|
|
import { CollapsibleContent, CollapsibleTrigger } from '@kit/ui/collapsible';
|
|
import {
|
|
Sidebar,
|
|
SidebarGroup,
|
|
SidebarGroupContent,
|
|
SidebarMenu,
|
|
SidebarMenuButton,
|
|
SidebarMenuItem,
|
|
SidebarMenuSub,
|
|
} from '@kit/ui/sidebar';
|
|
|
|
import { DocsNavLink } from '../_components/docs-nav-link';
|
|
import { DocsNavigationCollapsible } from '../_components/docs-navigation-collapsible';
|
|
import { FloatingDocumentationNavigationButton } from './floating-docs-navigation-button';
|
|
|
|
function Node({
|
|
node,
|
|
level,
|
|
prefix,
|
|
}: {
|
|
node: Cms.ContentItem;
|
|
level: number;
|
|
prefix: string;
|
|
}) {
|
|
const url = `${prefix}/${node.slug}`;
|
|
const label = node.label ? node.label : node.title;
|
|
|
|
return (
|
|
<NodeContainer node={node} prefix={prefix}>
|
|
<NodeTrigger node={node} label={label} url={url} />
|
|
|
|
<NodeContentContainer node={node}>
|
|
<Tree pages={node.children ?? []} level={level + 1} prefix={prefix} />
|
|
</NodeContentContainer>
|
|
</NodeContainer>
|
|
);
|
|
}
|
|
|
|
function NodeContentContainer({
|
|
node,
|
|
children,
|
|
}: {
|
|
node: Cms.ContentItem;
|
|
children: React.ReactNode;
|
|
}) {
|
|
if (node.collapsible) {
|
|
return <CollapsibleContent>{children}</CollapsibleContent>;
|
|
}
|
|
|
|
return children;
|
|
}
|
|
|
|
function NodeContainer({
|
|
node,
|
|
prefix,
|
|
children,
|
|
}: {
|
|
node: Cms.ContentItem;
|
|
prefix: string;
|
|
children: React.ReactNode;
|
|
}) {
|
|
if (node.collapsible) {
|
|
return (
|
|
<DocsNavigationCollapsible node={node} prefix={prefix}>
|
|
{children}
|
|
</DocsNavigationCollapsible>
|
|
);
|
|
}
|
|
|
|
return children;
|
|
}
|
|
|
|
function NodeTrigger({
|
|
node,
|
|
label,
|
|
url,
|
|
}: {
|
|
node: Cms.ContentItem;
|
|
label: string;
|
|
url: string;
|
|
}) {
|
|
if (node.collapsible) {
|
|
return (
|
|
<CollapsibleTrigger render={<SidebarMenuItem />}>
|
|
<SidebarMenuButton>
|
|
{label}
|
|
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
|
|
</SidebarMenuButton>
|
|
</CollapsibleTrigger>
|
|
);
|
|
}
|
|
|
|
return <DocsNavLink label={label} url={url} />;
|
|
}
|
|
|
|
function Tree({
|
|
pages,
|
|
level,
|
|
prefix,
|
|
}: {
|
|
pages: Cms.ContentItem[];
|
|
level: number;
|
|
prefix: string;
|
|
}) {
|
|
if (level === 0) {
|
|
return pages.map((treeNode, index) => (
|
|
<Node key={index} node={treeNode} level={level} prefix={prefix} />
|
|
));
|
|
}
|
|
|
|
if (pages.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<SidebarMenuSub>
|
|
{pages.map((treeNode, index) => (
|
|
<Node key={index} node={treeNode} level={level} prefix={prefix} />
|
|
))}
|
|
</SidebarMenuSub>
|
|
);
|
|
}
|
|
|
|
export function DocsNavigation({
|
|
pages,
|
|
prefix = '/docs',
|
|
}: {
|
|
pages: Cms.ContentItem[];
|
|
prefix?: string;
|
|
}) {
|
|
return (
|
|
<>
|
|
<Sidebar variant={'floating'}>
|
|
<SidebarGroup>
|
|
<SidebarGroupContent>
|
|
<SidebarMenu className={'pb-48'}>
|
|
<Tree pages={pages} level={0} prefix={prefix} />
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
</Sidebar>
|
|
|
|
<FloatingDocumentationNavigationButton />
|
|
</>
|
|
);
|
|
}
|