Skip to content

Commit 94dbcef

Browse files
authored
fix: simplify docs sidebar navigation
Closes #13 The documentation index now uses the docs shell, and the sidebar matches Cntryl structure with labeled groups and plain links.
1 parent edea43c commit 94dbcef

4 files changed

Lines changed: 45 additions & 126 deletions

File tree

scripts/verify-static-output.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,36 +22,26 @@ const apiSymbolsByRoute = new Map(
2222
apiSymbolSets[entrypoint.symbolSet as keyof typeof apiSymbolSets],
2323
])
2424
);
25-
const docsHome = docsCatalog.find((page) => page.route === '/docs');
26-
if (!docsHome) throw new Error('Missing /docs catalog entry');
27-
2825
const marketing = [
2926
{ route: '/', ...marketingRouteMetadata['/'] },
3027
...marketingPages.map((page) => ({
3128
route: page.path,
3229
title: page.title,
3330
description: page.description,
3431
})),
35-
{
36-
route: '/docs',
37-
title: `${docsHome.title} | Askr`,
38-
description: docsHome.description,
39-
},
4032
{ route: '/404', ...marketingRouteMetadata['/404'] },
4133
].map((page) => ({ ...page, layout: 'marketing' }));
4234

43-
const docs = docsCatalog
44-
.filter((page) => page.route !== '/docs')
45-
.map((page) => ({
46-
route: page.route,
47-
title: `${page.title} | Askr`,
48-
description: page.description,
49-
headings: page.headings.map(({ id }) => ({ id })),
50-
apiSymbols: apiSymbolsByRoute
51-
.get(page.route)
52-
?.map(({ anchor }) => ({ anchor })),
53-
layout: 'docs',
54-
}));
35+
const docs = docsCatalog.map((page) => ({
36+
route: page.route,
37+
title: `${page.title} | Askr`,
38+
description: page.description,
39+
headings: page.headings.map(({ id }) => ({ id })),
40+
apiSymbols: apiSymbolsByRoute
41+
.get(page.route)
42+
?.map(({ anchor }) => ({ anchor })),
43+
layout: 'docs',
44+
}));
5545

5646
const expectations = [...marketing, ...docs];
5747
const expectedRoutes = new Set(expectations.map(({ route }) => route));

src/pages/_routes.tsx

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
} from './marketing/_routes';
77
import { DocsLayout } from './docs/_layout';
88
import { docsCatalog } from './docs/catalog';
9-
import { MarketingLayout } from './marketing/_layout';
109

1110
export type { RouteMetadata } from './marketing/_routes';
1211

@@ -23,15 +22,8 @@ export const routeMetadata: Readonly<Record<string, RouteMetadata>> = {
2322
export const routeRegistry = createRouteRegistry(() => {
2423
registerMarketingRoutes();
2524

26-
const docsHome = docsCatalog.find((page) => page.route === '/docs');
27-
if (!docsHome) throw new Error('Missing /docs catalog entry');
28-
group({ layout: MarketingLayout }, () => {
29-
route('/docs', lazy(docsHome.loader), { meta: routeMetadata['/docs'] });
30-
});
31-
3225
group({ layout: DocsLayout }, () => {
3326
for (const page of docsCatalog) {
34-
if (page.route === '/docs') continue;
3527
route(page.route, lazy(page.loader), {
3628
meta: routeMetadata[page.route],
3729
});
@@ -49,20 +41,8 @@ export async function createStaticRouteRegistry() {
4941
const registry = createRouteRegistry(() => {
5042
registerMarketingRoutes();
5143

52-
const docsHome = docsCatalog.find((page) => page.route === '/docs');
53-
if (!docsHome) throw new Error('Missing /docs catalog entry');
54-
group({ layout: MarketingLayout }, () => {
55-
let component = components.get(docsHome.loader);
56-
if (!component) {
57-
component = lazy(docsHome.loader);
58-
components.set(docsHome.loader, component);
59-
}
60-
route('/docs', component, { meta: routeMetadata['/docs'] });
61-
});
62-
6344
group({ layout: DocsLayout }, () => {
6445
for (const page of docsCatalog) {
65-
if (page.route === '/docs') continue;
6646
let component = components.get(page.loader);
6747
if (!component) {
6848
component = lazy(page.loader);

src/pages/docs/_layout.tsx

Lines changed: 33 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,6 @@ import {
1313
SidebarScope,
1414
SidebarTrigger,
1515
} from '@askrjs/themes/components';
16-
import {
17-
BookOpenIcon,
18-
CompassIcon,
19-
Layers3Icon,
20-
LibraryIcon,
21-
MonitorIcon,
22-
PanelsTopLeftIcon,
23-
RocketIcon,
24-
RouteIcon,
25-
ServerIcon,
26-
WrenchIcon,
27-
} from '@askrjs/lucide';
2816
import { SiteLayout } from '../site-layout';
2917
import {
3018
docsByRoute,
@@ -35,84 +23,44 @@ import {
3523

3624
function DocsNavigation({ close }: { close?: () => void }) {
3725
const activePath = resolveDocsRoute(currentRoute());
38-
const sectionIcons = [
39-
BookOpenIcon,
40-
RocketIcon,
41-
Layers3Icon,
42-
RouteIcon,
43-
MonitorIcon,
44-
ServerIcon,
45-
PanelsTopLeftIcon,
46-
WrenchIcon,
47-
CompassIcon,
48-
LibraryIcon,
49-
] as const;
5026

5127
return (
5228
<SidebarContent as="nav" aria-label="Documentation navigation">
53-
{docsSections.map((section, sectionIndex) => {
54-
const active = section.pages.some((page) => page.route === activePath);
55-
const SectionIcon = sectionIcons[sectionIndex] ?? BookOpenIcon;
56-
const subsections = section.pages.reduce((groups, page) => {
57-
const label = page.navSection ?? section.label;
58-
const pages = groups.get(label) ?? [];
59-
pages.push(page);
60-
groups.set(label, pages);
61-
return groups;
62-
}, new Map<string, (typeof section.pages)[number][]>());
63-
29+
{docsSections.map((section) => {
6430
return (
65-
<SidebarGroup data-nav-section={section.id}>
66-
<SidebarMenu>
67-
<SidebarMenuItem>
68-
<SidebarMenuButton asChild active={active}>
69-
<Link href={section.landingRoute} onClick={close}>
70-
<SectionIcon size={18} aria-hidden="true" />
71-
<span>{section.label}</span>
72-
</Link>
73-
</SidebarMenuButton>
74-
</SidebarMenuItem>
75-
</SidebarMenu>
76-
{active && (
77-
<SidebarGroupContent>
78-
{Array.from(subsections).map(([label, pages]) => (
79-
<div>
80-
{label !== section.label && (
81-
<SidebarGroupLabel>{label}</SidebarGroupLabel>
82-
)}
83-
<SidebarMenu>
84-
{pages.map((page) => (
85-
<SidebarMenuItem>
86-
<SidebarMenuButton
87-
asChild
88-
active={page.route === activePath}
89-
size="sm"
31+
<SidebarGroup key={section.id} data-nav-section={section.id}>
32+
<SidebarGroupLabel>{section.label}</SidebarGroupLabel>
33+
<SidebarGroupContent>
34+
<SidebarMenu>
35+
{section.pages.map((page) => (
36+
<SidebarMenuItem key={page.route}>
37+
<SidebarMenuButton
38+
asChild
39+
active={page.route === activePath}
40+
size="sm"
41+
>
42+
<Link
43+
href={page.route}
44+
aria-current={
45+
page.route === activePath ? 'page' : undefined
46+
}
47+
onClick={close}
48+
>
49+
<span>{page.title}</span>
50+
{page.status !== 'stable' && (
51+
<span
52+
class="docs-sidebar-nav__status"
53+
title={page.status}
9054
>
91-
<Link
92-
href={page.route}
93-
aria-current={
94-
page.route === activePath ? 'page' : undefined
95-
}
96-
onClick={close}
97-
>
98-
<span>{page.title}</span>
99-
{page.status !== 'stable' && (
100-
<span
101-
class="docs-sidebar-nav__status"
102-
title={page.status}
103-
>
104-
105-
</span>
106-
)}
107-
</Link>
108-
</SidebarMenuButton>
109-
</SidebarMenuItem>
110-
))}
111-
</SidebarMenu>
112-
</div>
55+
56+
</span>
57+
)}
58+
</Link>
59+
</SidebarMenuButton>
60+
</SidebarMenuItem>
11361
))}
114-
</SidebarGroupContent>
115-
)}
62+
</SidebarMenu>
63+
</SidebarGroupContent>
11664
</SidebarGroup>
11765
);
11866
})}
@@ -130,7 +78,7 @@ function TableOfContents() {
13078
<p>On this page</p>
13179
<ul>
13280
{headings.map((heading) => (
133-
<li>
81+
<li key={heading.id}>
13482
<a href={`#${heading.id}`}>{heading.title}</a>
13583
</li>
13684
))}

src/pages/docs/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ function HeadingContent({
8383
}: {
8484
item: DocsHeadingDefinition;
8585
page: DocsPageDefinition;
86+
[prop: string]: unknown;
8687
}) {
8788
return (
8889
<section aria-labelledby={item.id}>
@@ -186,7 +187,7 @@ export default function DocsPage() {
186187
<UsageGuide page={page} />
187188
<ComponentDemo page={page} />
188189
{page.headings.map((item) => (
189-
<HeadingContent item={item} page={page} />
190+
<HeadingContent key={item.id} item={item} page={page} />
190191
))}
191192
{page.route === '/docs' && (
192193
<>

0 commit comments

Comments
 (0)