Files
copilotkit__copilotkit/docs/components/layout/conditional-sidebar.tsx
Tyler Slaton 760fc65187 feat(docs): scope sidebar to /learn with header + Overview landing
Add a Learn-only sidebar mode that mirrors how /reference works: when a user
is under /learn, the framework picker is hidden and the sidebar shows only
learn content (What's New, Agentic Protocols, Generative UI, Specs,
Architecture, Tutorials).

- Add `learn` to the root meta.json so the learn folder is discoverable in
  the page tree (was missing, which is why ConditionalSidebar previously
  fell through to the default sidebar on /learn routes)
- Add a static LearnHeader (book icon + "Learn") visually matching the
  Reference version selector, wired in via Sidebar's headerSlot
- Rename the learn index page title to "Overview" so the landing page reads
  cleanly under the new header
- Drop the redundant `h-6` spacer in Sidebar — every header component
  (IntegrationSelector, VersionSelector, LearnHeader) already supplies its
  own `mb-3`, and the spacer was producing a 24px phantom gap on /learn
  while collapsing to 0 on /reference under flex shrink

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-04 20:49:48 -07:00

139 lines
4.4 KiB
TypeScript

"use client";
import { usePathname } from "next/navigation";
import { DocsLayoutProps } from "fumadocs-ui/layouts/docs";
import Sidebar from "./sidebar";
import IntegrationsSidebar from "./integrations-sidebar";
import { INTEGRATION_ORDER } from "@/lib/integrations";
const DEPLOY_ROUTES = ["agentcore"];
import { normalizeUrl } from "@/lib/analytics-utils";
import { useMemo } from "react";
import VersionSelector, {
getVersionFromPathname,
} from "@/components/ui/reference-sidebar/version-selector";
import LearnHeader from "@/components/ui/learn-sidebar/learn-header";
interface ConditionalSidebarProps {
pageTree: DocsLayoutProps["tree"];
}
type Node = DocsLayoutProps["tree"]["children"][number];
export default function ConditionalSidebar({
pageTree,
}: ConditionalSidebarProps) {
const pathname = usePathname();
// Normalize the pathname to handle /integrations/... paths
const normalizedPathname = normalizeUrl(pathname);
// Check if this is an integration landing page (e.g., /langgraph)
// Use the first segment of the normalized pathname to ensure correct matching
const firstSegment = normalizedPathname.replace(/^\//, "").split("/")[0];
const isIntegrationRoute =
INTEGRATION_ORDER.includes(
firstSegment as (typeof INTEGRATION_ORDER)[number],
) || DEPLOY_ROUTES.includes(firstSegment);
// Check if this is a reference route (e.g., /reference)
const isReferenceRoute = firstSegment === "reference";
// Check if this is a learn route (e.g., /learn)
const isLearnRoute = firstSegment === "learn";
const currentVersion = getVersionFromPathname(pathname);
// Find the learn folder and use its children
const learnPageTree = useMemo(() => {
if (!isLearnRoute) return null;
const learnFolder = pageTree.children.find((node) => {
if (node.type !== "folder") return false;
const folderNode = node as any;
const url = folderNode.index?.url || folderNode.url;
const name =
typeof folderNode.name === "string" ? folderNode.name : undefined;
return url === "/learn" || name?.toLowerCase() === "learn";
}) as Node | undefined;
if (learnFolder && "children" in learnFolder) {
return {
...pageTree,
children: (learnFolder as any).children || [],
};
}
return null;
}, [isLearnRoute, pageTree]);
// Find the reference folder and drill into the active version
const referencePageTree = useMemo(() => {
if (!isReferenceRoute) return null;
// Find the reference folder
const referenceFolder = pageTree.children.find((node) => {
if (node.type !== "folder") return false;
const folderNode = node as any;
const url = folderNode.index?.url || folderNode.url;
const name =
typeof folderNode.name === "string" ? folderNode.name : undefined;
return url === "/reference" || name?.toLowerCase() === "reference";
}) as Node | undefined;
if (referenceFolder && "children" in referenceFolder) {
const referenceChildren = (referenceFolder as any).children || [];
// Find the version folder (v1 or v2) within the reference folder
const versionFolder = referenceChildren.find((node: any) => {
if (node.type !== "folder") return false;
const url = node.index?.url || node.url;
const name = typeof node.name === "string" ? node.name : undefined;
return (
url === `/reference/${currentVersion}` ||
name?.toLowerCase() === currentVersion
);
});
if (versionFolder && "children" in versionFolder) {
// Return a pageTree with only the version folder's children
return {
...pageTree,
children: (versionFolder as any).children || [],
};
}
// Fallback: return the reference folder's children directly
return {
...pageTree,
children: referenceChildren,
};
}
return null;
}, [isReferenceRoute, pageTree, currentVersion]);
if (isIntegrationRoute) {
return <IntegrationsSidebar pageTree={pageTree} />;
}
if (isLearnRoute && learnPageTree) {
return (
<Sidebar
pageTree={learnPageTree}
showIntegrationSelector={false}
headerSlot={<LearnHeader />}
/>
);
}
if (isReferenceRoute && referencePageTree) {
return (
<Sidebar
pageTree={referencePageTree}
showIntegrationSelector={false}
headerSlot={<VersionSelector />}
/>
);
}
return <Sidebar pageTree={pageTree} />;
}