Skip to content

Commit e164c92

Browse files
xuyushun441-sysos-zhuangclaude
authored
feat(ADR-0046): lightweight chrome (DocShell) for the docs routes (#1690)
The /docs portal and /docs/:name viewer are app-independent top-level routes, so they rendered bare (no header, no way back) — looked unfinished. Add a minimal sticky DocShell header shared by both: a "Documentation" home link (→ /docs) plus a breadcrumb of the current doc. No app sidebar (keeps ADR-0046's "no nav taxonomy in v1"), just orientation + a way out. The portal's redundant in-body "Documentation" title is dropped in favour of the header. Verified live: portal shows header + grouped list; doc page shows "Documentation / <doc>" breadcrumb + typography-styled body; header back-link returns to the portal. No console errors. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8d37b31 commit e164c92

4 files changed

Lines changed: 90 additions & 25 deletions

File tree

.changeset/adr-0046-docs-shell.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
"@object-ui/console": patch
3+
---
4+
5+
feat(ADR-0046): lightweight chrome for the docs routes.
6+
7+
The `/docs` portal and `/docs/:name` viewer are app-independent top-level
8+
routes, so they rendered as bare full-bleed pages with no header and no way
9+
back. Add a minimal sticky `DocShell` header — a "Documentation" home link
10+
(→ `/docs`) plus a breadcrumb of the current doc — shared by the portal and the
11+
viewer. Keeps ADR-0046's "no nav taxonomy in v1" intent (no app sidebar) while
12+
giving readers orientation and a way out. The portal's redundant in-body title
13+
is dropped in favour of the header.

apps/console/src/pages/DocPage.tsx

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { AlertCircle, FileQuestion, Loader2 } from 'lucide-react';
1212
import { useAdapter } from '@object-ui/app-shell';
1313
import { MarkdownRenderer } from '@object-ui/plugin-markdown';
1414
import { rewriteDocLinks } from './doc-links';
15+
import { DocShell } from './DocShell';
1516

1617
interface DocItem {
1718
name: string;
@@ -100,32 +101,38 @@ export default function DocPage() {
100101

101102
if (state === 'missing') {
102103
return (
103-
<div className="mx-auto flex max-w-3xl flex-col items-center gap-3 p-10 text-center">
104-
<FileQuestion className="h-10 w-10 text-muted-foreground" />
105-
<h1 className="text-lg font-semibold">Documentation not found</h1>
106-
<p className="text-sm text-muted-foreground">
107-
No document named <code className="rounded bg-muted px-1 py-0.5">{name}</code> is installed.
108-
It may belong to a package that is not installed, or it was removed in a newer version.
109-
</p>
110-
</div>
104+
<DocShell breadcrumb={name}>
105+
<div className="mx-auto flex max-w-3xl flex-col items-center gap-3 p-10 text-center">
106+
<FileQuestion className="h-10 w-10 text-muted-foreground" />
107+
<h1 className="text-lg font-semibold">Documentation not found</h1>
108+
<p className="text-sm text-muted-foreground">
109+
No document named <code className="rounded bg-muted px-1 py-0.5">{name}</code> is installed.
110+
It may belong to a package that is not installed, or it was removed in a newer version.
111+
</p>
112+
</div>
113+
</DocShell>
111114
);
112115
}
113116

114117
if (state === 'error') {
115118
return (
116-
<div className="mx-auto flex max-w-3xl flex-col items-center gap-3 p-10 text-center">
117-
<AlertCircle className="h-10 w-10 text-destructive" />
118-
<h1 className="text-lg font-semibold">Failed to load documentation</h1>
119-
<p className="text-sm text-muted-foreground">{errorMessage}</p>
120-
</div>
119+
<DocShell breadcrumb={name}>
120+
<div className="mx-auto flex max-w-3xl flex-col items-center gap-3 p-10 text-center">
121+
<AlertCircle className="h-10 w-10 text-destructive" />
122+
<h1 className="text-lg font-semibold">Failed to load documentation</h1>
123+
<p className="text-sm text-muted-foreground">{errorMessage}</p>
124+
</div>
125+
</DocShell>
121126
);
122127
}
123128

124129
return (
125-
<div className="mx-auto max-w-3xl p-4 sm:p-6" onClick={onContentClick}>
126-
<MarkdownRenderer
127-
schema={{ type: 'markdown', content: rewriteDocLinks(doc?.content ?? '') }}
128-
/>
129-
</div>
130+
<DocShell breadcrumb={doc?.label ?? name}>
131+
<div className="mx-auto max-w-3xl p-4 sm:p-6" onClick={onContentClick}>
132+
<MarkdownRenderer
133+
schema={{ type: 'markdown', content: rewriteDocLinks(doc?.content ?? '') }}
134+
/>
135+
</div>
136+
</DocShell>
130137
);
131138
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* ObjectUI
3+
* Copyright (c) 2024-present ObjectStack Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
import type { ReactNode } from 'react';
10+
import { Link } from 'react-router-dom';
11+
import { BookOpen } from 'lucide-react';
12+
13+
/**
14+
* Lightweight chrome for the package-documentation routes (ADR-0046).
15+
*
16+
* The doc viewer/portal are app-independent top-level routes, so they don't
17+
* get the console's app sidebar. This adds a minimal sticky header — a
18+
* "Documentation" home link (→ `/docs`) plus an optional breadcrumb — so a
19+
* reader always knows where they are and has a way back, without pulling in
20+
* the full app shell (which ADR-0046 deliberately keeps out of v1).
21+
*/
22+
export function DocShell({ breadcrumb, children }: { breadcrumb?: string; children: ReactNode }) {
23+
return (
24+
<div className="min-h-full">
25+
<header className="sticky top-0 z-10 border-b border-border bg-background/80 backdrop-blur supports-[backdrop-filter]:bg-background/60">
26+
<div className="mx-auto flex max-w-3xl items-center gap-2 px-4 py-3 sm:px-6">
27+
<Link
28+
to="/docs"
29+
className="flex items-center gap-2 text-sm font-semibold hover:opacity-80"
30+
>
31+
<BookOpen className="h-4 w-4 text-muted-foreground" />
32+
<span>Documentation</span>
33+
</Link>
34+
{breadcrumb ? (
35+
<>
36+
<span className="text-muted-foreground/60" aria-hidden>
37+
/
38+
</span>
39+
<span className="truncate text-sm text-muted-foreground">{breadcrumb}</span>
40+
</>
41+
) : null}
42+
</div>
43+
</header>
44+
{children}
45+
</div>
46+
);
47+
}

apps/console/src/pages/DocsIndex.tsx

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Link } from 'react-router-dom';
1111
import { AlertCircle, BookOpen, Loader2 } from 'lucide-react';
1212
import { useAdapter } from '@object-ui/app-shell';
1313
import { type DocGroup, groupDocsByPackage } from './doc-groups';
14+
import { DocShell } from './DocShell';
1415

1516
/**
1617
* `/docs` — the platform-level documentation portal (ADR-0046).
@@ -86,12 +87,8 @@ export default function DocsIndex() {
8687
}
8788

8889
return (
89-
<div className="mx-auto max-w-3xl p-4 sm:p-6">
90-
<div className="mb-6 flex items-center gap-2">
91-
<BookOpen className="h-6 w-6 text-muted-foreground" />
92-
<h1 className="text-2xl font-semibold">Documentation</h1>
93-
</div>
94-
90+
<DocShell>
91+
<div className="mx-auto max-w-3xl p-4 sm:p-6">
9592
{groups.length === 0 ? (
9693
<div className="flex flex-col items-center gap-3 py-16 text-center text-muted-foreground">
9794
<BookOpen className="h-10 w-10" />
@@ -126,6 +123,7 @@ export default function DocsIndex() {
126123
))}
127124
</div>
128125
)}
129-
</div>
126+
</div>
127+
</DocShell>
130128
);
131129
}

0 commit comments

Comments
 (0)