forked from CopilotKit/CopilotKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell-docs-layout.tsx
More file actions
118 lines (117 loc) · 5.31 KB
/
Copy pathshell-docs-layout.tsx
File metadata and controls
118 lines (117 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import React from "react";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import type * as PageTree from "fumadocs-core/page-tree";
import { MobileTopNav } from "./mobile-top-nav";
import { SidebarScrollPreserver } from "./sidebar-scroll-preserver";
import { SidebarFolderStatePreserver } from "./sidebar-folder-state-preserver";
import { SidebarReactDocsNotice } from "./sidebar-react-docs-notice";
import GithubIcon from "./icons/github";
import DiscordIcon from "./icons/discord";
import { MobileSidebarFooterTalk } from "./mobile-sidebar-footer-talk";
import { PrimaryDocsTabs } from "./primary-docs-tabs";
// Shared Fumadocs `DocsLayout` chrome used by every shell-docs route.
// All five callers (home overview, framework root, framework-scoped MDX
// via DocsPageView, /reference, /ag-ui) pass the same nav/search/sidebar
// config — only `tree` and `sidebar.banner` vary. Centralizing keeps
// sidebar behavior, mobile nav slot, and container className from drifting
// across routes when one is tweaked.
export function ShellDocsLayout({
tree,
banner,
sidebarClassName,
children,
}: {
tree: PageTree.Root;
banner?: React.ReactNode;
sidebarClassName?: string;
children: React.ReactNode;
}) {
return (
<DocsLayout
tree={tree}
nav={{ component: <MobileTopNav /> }}
searchToggle={{ enabled: false }}
// Suppress fumadocs's auto-injected ThemeSwitch — `slots.themeSwitch`
// is populated by default even when `themeSwitch` isn't passed, so
// we have to pass `enabled: false` explicitly to keep the
// `iconLinks.length > 0 || slots.themeSwitch` branch in
// `sidebar.js` from rendering the default rounded pill. Our own
// single-toggle `<ThemeSwitch>` is mounted in BrandNav instead.
themeSwitch={{ enabled: false }}
// We intentionally do NOT pass `links` here either. Fumadocs would
// funnel `type: "icon"` entries into the same auto-injected pill
// we just disabled — but the icons need to live in our custom
// footer row anyway. Rendering them inline keeps a single source
// of truth (the JSX below) and avoids the auto layout fighting
// our custom one.
sidebar={{
banner: (
<div key="shell-docs-sidebar-banner" className="flex flex-col">
<PrimaryDocsTabs className="shell-docs-mobile-sidebar-tabs" />
{banner}
</div>
),
// Hide Fumadocs's collapse toggle — shell-docs has its own chrome.
collapsible: false,
className: ["shell-docs-sidebar", sidebarClassName]
.filter(Boolean)
.join(" "),
// Note: `key` is required here because fumadocs's Sidebar
// passes the `footer` ReactNode into a `jsxs(children: [a, b,
// footer])` array, and React's dev-mode warning insists every
// top-level child of an array carry a stable key. We don't
// control fumadocs's render, so we hand it a keyed element
// directly. The key is a literal string — there's only ever
// one footer per sidebar.
footer: (
<div
key="shell-docs-sidebar-footer"
className="flex w-full flex-col gap-2 sidebar-footer-row md:w-auto md:flex-row md:items-center md:gap-1"
>
<MobileSidebarFooterTalk />
<div className="flex items-center gap-1">
<a
href="https://github.com/copilotkit/copilotkit"
target="_blank"
rel="noreferrer noopener"
aria-label="GitHub"
className="shell-docs-radius-control inline-flex h-7 w-7 items-center justify-center text-[var(--text-muted)] transition-colors hover:bg-[var(--bg-elevated)] hover:text-[var(--text)] [&_svg]:size-4"
>
<GithubIcon />
</a>
<a
href="https://discord.gg/6dffbvGU3D"
target="_blank"
rel="noreferrer noopener"
aria-label="Discord"
className="shell-docs-radius-control inline-flex h-7 w-7 items-center justify-center text-[var(--text-muted)] transition-colors hover:bg-[var(--bg-elevated)] hover:text-[var(--text)] [&_svg]:size-4"
>
<DiscordIcon />
</a>
</div>
</div>
),
}}
containerProps={{
// The outer .docs-content-wrapper gradient + scroll behavior is
// applied to DocsLayout's container so the scroll context, border,
// and gradient match what shell-docs has always rendered.
className: "docs-content-wrapper",
}}
>
{/* Preserve sidebar scroll across navigations — the sidebar is
* rendered per-page (this layout sits inside each page component
* rather than in a Next.js layout file), so without explicit
* restoration the Radix ScrollAreaViewport resets to 0 every
* time the user clicks a link further down the list. */}
<SidebarScrollPreserver />
{/* Persist sidebar folder open/closed state across navigations —
* without this, Fumadocs resets each Radix Collapsible to its
* default state on every page mount, undoing the user's
* "I want this section hidden" choice. */}
<SidebarFolderStatePreserver />
<SidebarReactDocsNotice />
{children}
</DocsLayout>
);
}