Skip to content

Commit c92a8c2

Browse files
committed
fix: sidebar behaviour when switching package/version
1 parent 14e226b commit c92a8c2

File tree

18 files changed

+377
-208
lines changed

18 files changed

+377
-208
lines changed

apps/website/next.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export default {
2222
experimental: {
2323
ppr: true,
2424
reactCompiler: true,
25-
useCache: true,
2625
dynamicOnHover: true,
2726
},
2827
eslint: {

apps/website/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"dependencies": {
4949
"@radix-ui/react-collapsible": "^1.1.3",
5050
"@react-icons/all-files": "^4.1.0",
51+
"@tanstack/react-query": "^5.76.1",
5152
"@vercel/analytics": "^1.5.0",
5253
"@vercel/edge-config": "^1.4.0",
5354
"@vercel/postgres": "^0.10.0",
@@ -61,7 +62,7 @@
6162
"lucide-react": "^0.503.0",
6263
"meilisearch": "^0.49.0",
6364
"motion": "^12.9.2",
64-
"next": "15.4.0-canary.31",
65+
"next": "15.4.0-canary.35",
6566
"next-mdx-remote-client": "^2.1.1",
6667
"next-themes": "^0.4.6",
6768
"nuqs": "^2.4.3",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { NextResponse, type NextRequest } from 'next/server';
2+
import { fetchEntryPoints } from '@/util/fetchEntryPoints';
3+
4+
export async function GET(request: NextRequest) {
5+
const { searchParams } = request.nextUrl;
6+
const packageName = searchParams.get('packageName');
7+
const version = searchParams.get('version');
8+
9+
if (!packageName || !version) {
10+
return NextResponse.json({ error: 'Missing required parameters' }, { status: 400 });
11+
}
12+
13+
const response = await fetchEntryPoints(packageName, version);
14+
15+
return NextResponse.json(response);
16+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { NextResponse, type NextRequest } from 'next/server';
2+
import { fetchSitemap } from '@/util/fetchSitemap';
3+
4+
export async function GET(request: NextRequest) {
5+
const { searchParams } = request.nextUrl;
6+
const packageName = searchParams.get('packageName');
7+
const version = searchParams.get('version');
8+
const entryPoint = searchParams.get('entryPoint');
9+
10+
if (!packageName || !version) {
11+
return NextResponse.json({ error: 'Missing required parameters' }, { status: 400 });
12+
}
13+
14+
const response = await fetchSitemap({
15+
entryPoint,
16+
packageName,
17+
version,
18+
});
19+
20+
return NextResponse.json(response);
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { NextResponse, type NextRequest } from 'next/server';
2+
import { fetchVersions } from '@/util/fetchVersions';
3+
4+
export async function GET(request: NextRequest) {
5+
const { searchParams } = request.nextUrl;
6+
const packageName = searchParams.get('packageName');
7+
8+
if (!packageName) {
9+
return NextResponse.json({ error: 'Missing required parameters' }, { status: 400 });
10+
}
11+
12+
const response = await fetchVersions(packageName);
13+
14+
return NextResponse.json(response);
15+
}

apps/website/src/app/docs/packages/[packageName]/[version]/[[...item]]/layout.tsx

Lines changed: 2 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,5 @@
1-
'use cache';
2-
3-
import { VscGithubInverted } from '@react-icons/all-files/vsc/VscGithubInverted';
41
import type { Metadata } from 'next';
5-
import Link from 'next/link';
62
import { Suspense, type PropsWithChildren } from 'react';
7-
import { EntryPointSelect } from '@/components/EntrypointSelect';
8-
import { Footer } from '@/components/Footer';
9-
import { Navigation } from '@/components/Navigation';
10-
import { Scrollbars } from '@/components/OverlayScrollbars';
11-
import { PackageSelect } from '@/components/PackageSelect';
12-
import { SearchButton } from '@/components/SearchButton';
13-
import { ThemeSwitchNoSRR } from '@/components/ThemeSwitch';
14-
import { VersionSelect } from '@/components/VersionSelect';
15-
import { Sidebar, SidebarContent, SidebarHeader, SidebarInset, SidebarTrigger } from '@/components/ui/Sidebar';
16-
import { buttonStyles } from '@/styles/ui/button';
17-
import { PACKAGES_WITH_ENTRY_POINTS } from '@/util/constants';
18-
import { ENV } from '@/util/env';
19-
import { fetchEntryPoints } from '@/util/fetchEntryPoints';
20-
import { fetchVersions } from '@/util/fetchVersions';
21-
import { parseDocsPathParams } from '@/util/parseDocsPathParams';
223
import { CmdK } from './CmdK';
234

245
export async function generateMetadata({
@@ -44,82 +25,11 @@ export default async function Layout({
4425
params,
4526
children,
4627
}: PropsWithChildren<{
47-
readonly params: Promise<{
48-
readonly item?: string[] | undefined;
49-
readonly packageName: string;
50-
readonly version: string;
51-
}>;
28+
readonly params: Promise<{ readonly packageName: string; readonly version: string }>;
5229
}>) {
53-
const { packageName, version, item } = await params;
54-
55-
const versions = fetchVersions(packageName);
56-
57-
const hasEntryPoints = PACKAGES_WITH_ENTRY_POINTS.includes(packageName);
58-
59-
const entryPoints = hasEntryPoints ? fetchEntryPoints(packageName, version) : Promise.resolve([]);
60-
const { entryPoints: parsedEntrypoints } = parseDocsPathParams(item);
61-
6230
return (
6331
<>
64-
<Sidebar closeButton={false} intent="inset">
65-
<SidebarHeader className="bg-[#f3f3f4] p-4 dark:bg-[#121214]">
66-
<div className="flex flex-col gap-2">
67-
<div className="flex place-content-between place-items-center p-1">
68-
<Link className="text-xl font-bold" href={`/docs/packages/${packageName}/${version}`}>
69-
{packageName}
70-
</Link>
71-
<div className="flex place-items-center gap-2">
72-
<Link
73-
aria-label="GitHub"
74-
className={buttonStyles({ variant: 'filled', size: 'icon-sm' })}
75-
href="https://github.com/discordjs/discord.js"
76-
rel="external noopener noreferrer"
77-
target="_blank"
78-
>
79-
<VscGithubInverted aria-hidden data-slot="icon" size={18} />
80-
</Link>
81-
<ThemeSwitchNoSRR />
82-
</div>
83-
</div>
84-
<PackageSelect />
85-
{/* <h3 className="p-1 text-lg font-semibold">{version}</h3> */}
86-
<VersionSelect versionsPromise={versions} />
87-
{hasEntryPoints ? <EntryPointSelect entryPointsPromise={entryPoints} /> : null}
88-
<SearchButton />
89-
</div>
90-
</SidebarHeader>
91-
<SidebarContent className="bg-[#f3f3f4] p-0 py-4 pl-4 dark:bg-[#121214]">
92-
<Scrollbars>
93-
<Navigation entryPoint={parsedEntrypoints.join('.')} packageName={packageName} version={version} />
94-
</Scrollbars>
95-
</SidebarContent>
96-
</Sidebar>
97-
<SidebarInset>
98-
{ENV.IS_LOCAL_DEV ? (
99-
<div className="sticky top-0 z-10 flex place-content-center place-items-center border border-red-400/35 bg-red-500/65 p-2 px-4 text-center text-base text-white shadow-md backdrop-blur">
100-
Local test environment
101-
</div>
102-
) : null}
103-
{ENV.IS_PREVIEW ? (
104-
<div className="sticky top-0 z-10 flex place-content-center place-items-center border border-red-400/35 bg-red-500/65 p-2 px-4 text-center text-base text-white shadow-md backdrop-blur">
105-
Preview environment
106-
</div>
107-
) : null}
108-
<div className="bg-[#fbfbfb] pb-12 dark:bg-[#1a1a1e]">
109-
<div className="relative px-6 pt-6 md:hidden">
110-
<div className="fixed top-5 left-6 z-20 md:hidden">
111-
<SidebarTrigger aria-label="Navigation" size="icon" variant="filled" />
112-
</div>
113-
<div className="flex place-content-end">
114-
<Link className="text-xl font-bold" href={`/docs/packages/${packageName}/${version}`}>
115-
{packageName}
116-
</Link>
117-
</div>
118-
</div>
119-
{children}
120-
<Footer />
121-
</div>
122-
</SidebarInset>
32+
{children}
12333
<Suspense>
12434
<CmdK params={params} />
12535
</Suspense>

apps/website/src/app/docs/packages/[packageName]/[version]/[[...item]]/page.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use cache';
2-
31
import { readFile } from 'node:fs/promises';
42
import { join } from 'node:path';
53
import rehypeShikiFromHighlighter from '@shikijs/rehype/core';
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// import Link from 'next/link';
2+
import type { PropsWithChildren } from 'react';
3+
import { Footer } from '@/components/Footer';
4+
import { Navigation } from '@/components/Navigation';
5+
import { Scrollbars } from '@/components/OverlayScrollbars';
6+
import { SidebarHeader } from '@/components/Sidebar';
7+
import { Sidebar, SidebarContent, SidebarInset, SidebarTrigger } from '@/components/ui/Sidebar';
8+
import { ENV } from '@/util/env';
9+
10+
export default async function Layout({ children }: PropsWithChildren) {
11+
return (
12+
<>
13+
<Sidebar closeButton={false} intent="inset">
14+
<SidebarHeader />
15+
<SidebarContent className="bg-[#f3f3f4] p-0 py-4 pl-4 dark:bg-[#121214]">
16+
<Scrollbars>
17+
<Navigation />
18+
</Scrollbars>
19+
</SidebarContent>
20+
</Sidebar>
21+
<SidebarInset>
22+
{ENV.IS_LOCAL_DEV ? (
23+
<div className="sticky top-0 z-10 flex place-content-center place-items-center border border-red-400/35 bg-red-500/65 p-2 px-4 text-center text-base text-white shadow-md backdrop-blur">
24+
Local test environment
25+
</div>
26+
) : null}
27+
{ENV.IS_PREVIEW ? (
28+
<div className="sticky top-0 z-10 flex place-content-center place-items-center border border-red-400/35 bg-red-500/65 p-2 px-4 text-center text-base text-white shadow-md backdrop-blur">
29+
Preview environment
30+
</div>
31+
) : null}
32+
<div className="bg-[#fbfbfb] pb-12 dark:bg-[#1a1a1e]">
33+
<div className="relative px-6 pt-6 md:hidden">
34+
<div className="fixed top-5 left-6 z-20 md:hidden">
35+
<SidebarTrigger aria-label="Navigation" size="icon" variant="filled" />
36+
</div>
37+
{/* <div className="flex place-content-end">
38+
<Link className="text-xl font-bold" href={`/docs/packages/${packageName}/${version}`}>
39+
{packageName}
40+
</Link>
41+
</div> */}
42+
</div>
43+
{children}
44+
<Footer />
45+
</div>
46+
</SidebarInset>
47+
</>
48+
);
49+
}

apps/website/src/app/providers.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { isServer, QueryClient, QueryClientProvider } from '@tanstack/react-query';
34
import { Provider as JotaiProvider } from 'jotai';
45
import { useRouter } from 'next/navigation';
56
import { ThemeProvider } from 'next-themes';
@@ -10,7 +11,30 @@ import { SidebarProvider } from '@/components/ui/Sidebar';
1011
import { useSystemThemeFallback } from '@/hooks/useSystemThemeFallback';
1112
import { useUnregisterServiceWorker } from '@/hooks/useUnregisterServiceWorker';
1213

14+
function makeQueryClient() {
15+
return new QueryClient({
16+
defaultOptions: {
17+
queries: {
18+
staleTime: 60 * 1_000,
19+
},
20+
},
21+
});
22+
}
23+
24+
let browserQueryClient: QueryClient | undefined;
25+
26+
function getQueryClient() {
27+
if (isServer) {
28+
// Server: always make a new query client
29+
return makeQueryClient();
30+
} else {
31+
browserQueryClient ??= makeQueryClient();
32+
return browserQueryClient;
33+
}
34+
}
35+
1336
export function Providers({ children }: PropsWithChildren) {
37+
const queryClient = getQueryClient();
1438
const router = useRouter();
1539
useUnregisterServiceWorker();
1640
useSystemThemeFallback();
@@ -20,7 +44,9 @@ export function Providers({ children }: PropsWithChildren) {
2044
<ThemeProvider attribute="class">
2145
<RouterProvider navigate={router.push}>
2246
<JotaiProvider>
23-
<SidebarProvider defaultOpen>{children}</SidebarProvider>
47+
<QueryClientProvider client={queryClient}>
48+
<SidebarProvider defaultOpen>{children}</SidebarProvider>
49+
</QueryClientProvider>
2450
</JotaiProvider>
2551
</RouterProvider>
2652
</ThemeProvider>

apps/website/src/components/DocItem.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use cache';
2-
31
import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParameter';
42
import { ConstructorNode } from './ConstructorNode';
53
import { DeprecatedNode } from './DeprecatedNode';

0 commit comments

Comments
 (0)