Skip to content

Commit c52c083

Browse files
bloveclaude
andauthored
fix(website): docs polish 2/3 — breadcrumb, tables, rails, and mdx details (#863)
The detail third of the docs polish arc (findings §3, §4, §6-rail, §7, §9). - Breadcrumb typography moves to the list so the separators inherit it - they were siblings of the links and rendered 3px larger and 3px higher on the first two crumbs. Measured after: one font size, one baseline. - Tables get a 560px floor inside .docs-table-scroll so the scroller finally scrolls instead of crushing (375px rendered `agent` across three lines in a 49px column, rows 227px tall). Edge fades signal scrollability; the wrapper is tabIndex=0 role=region so keyboard users can reach the clipped columns (WCAG 2.1.1). ApiDocRenderer and ApiRefTable tables gain the same wrapper. - Inline code chips: word-break normal + overflow-wrap break-word - chips wrap whole instead of splitting @threadplane/langgraph into two pills. break-word, not anywhere: `anywhere` shrinks min-content to one character, which let table columns squeeze below chip width and wrap `agent` as agen/t (caught by measurement mid-implementation). - One horizontal rail: header, API block, and prev/next align down to the article's padding scale, ending the 8px left-edge mismatch below 640px. - Steps' dangling connector below the last step is gone (:last-child - the selector inline styles could never express). - The dead .shiki and [data-rehype-pretty-code-title] rules are deleted (findings §9: zero matching elements site-wide), with breadcrumb comments pointing at what to do if either ever comes back. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent d8dc3b0 commit c52c083

5 files changed

Lines changed: 65 additions & 33 deletions

File tree

apps/website/src/app/docs/[library]/[section]/[slug]/page.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export default async function DocsPage({ params }: DocsRouteProps) {
9292
<DocsSidebar activeLibrary={library as LibraryId} activeSection={section} activeSlug={slug} />
9393
<div className="flex-1 flex min-w-0 docs-shell-body">
9494
<div className="flex-1 min-w-0">
95-
<div className="px-6 md:px-12 pt-6">
95+
<div className="px-4 sm:px-6 md:px-12 pt-6">
9696
<DocsBreadcrumb library={library as LibraryId} section={section} slug={slug} title={doc.title} />
9797
<DocsPageHeader
9898
library={library as LibraryId}
@@ -123,14 +123,14 @@ export default async function DocsPage({ params }: DocsRouteProps) {
123123
: [byName(target) ?? byName(doc.title)].filter((e): e is ApiDocEntry => Boolean(e));
124124

125125
return rendered.length > 0 ? (
126-
<div className="px-6 md:px-12 max-w-3xl pb-8">
126+
<div className="px-4 sm:px-6 md:px-12 max-w-3xl pb-8">
127127
{rendered.map((entry) => (
128128
<ApiDocRenderer key={entry.name} entry={entry} />
129129
))}
130130
</div>
131131
) : null;
132132
})()}
133-
<div className="px-6 md:px-12 max-w-3xl pb-8">
133+
<div className="px-4 sm:px-6 md:px-12 max-w-3xl pb-8">
134134
<DocsPrevNext library={library as LibraryId} section={section} slug={slug} />
135135
</div>
136136
</div>

apps/website/src/components/docs/ApiDocRenderer.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function KindBadge({ kind }: { kind: string }) {
3232

3333
function ParamTable({ params }: { params: ApiParam[] }) {
3434
return (
35+
<div className="docs-table-scroll" tabIndex={0} role="region" aria-label="Parameters table, scrolls horizontally">
3536
<table className="api-doc-param-table">
3637
<thead>
3738
<tr>
@@ -50,6 +51,7 @@ function ParamTable({ params }: { params: ApiParam[] }) {
5051
))}
5152
</tbody>
5253
</table>
54+
</div>
5355
);
5456
}
5557

apps/website/src/components/docs/ApiRefTable.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export function ApiRefTable({ entries }: { entries: ApiEntry[] }) {
2424
</div>
2525
<p className="text-sm mb-4 api-ref-description">{entry.description}</p>
2626
{entry.params && entry.params.length > 0 && (
27+
<div className="docs-table-scroll" tabIndex={0} role="region" aria-label="Parameters table, scrolls horizontally">
2728
<table className="w-full text-xs api-ref-table">
2829
<thead>
2930
<tr>
@@ -46,6 +47,7 @@ export function ApiRefTable({ entries }: { entries: ApiEntry[] }) {
4647
))}
4748
</tbody>
4849
</table>
50+
</div>
4951
)}
5052
</div>
5153
))}

apps/website/src/components/docs/MdxRenderer.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ const mdxComponents = {
6262
);
6363
},
6464
table: ({ children, ...rest }: React.HTMLAttributes<HTMLTableElement>) => (
65-
<div className="docs-table-scroll">
65+
// tabIndex + role: a scrollable region must be keyboard-reachable
66+
// (WCAG 2.1.1) — without it, keyboard users can never see the clipped
67+
// columns the scroller hides.
68+
<div className="docs-table-scroll" tabIndex={0} role="region" aria-label="Table, scrolls horizontally">
6669
<table {...rest}>{children}</table>
6770
</div>
6871
),

apps/website/src/styles/docs.css

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,12 @@
3838
--docs-accent-tint-line: color-mix(in srgb, var(--color-accent) 10%, transparent);
3939
}
4040

41-
/* Shiki code blocks — tokyo-night theme */
42-
.shiki {
43-
padding: 1.5rem;
44-
background: var(--docs-code-bg) !important;
45-
overflow-x: auto;
46-
}
47-
.shiki code {
48-
font-family: var(--font-mono), monospace;
49-
font-size: 0.75rem;
50-
line-height: 1.7;
51-
}
41+
/* NOTE: the old `.shiki` rules were deleted here — rehype-pretty-code runs
42+
* with keepBackground:true, which writes the theme background INLINE on the
43+
* <pre> and never emits a .shiki class. Zero elements matched, on docs and
44+
* blog (findings §9). If keepBackground is ever turned off, style the code
45+
* background via [data-rehype-pretty-code-figure] pre, not a .shiki rule. */
46+
5247

5348
/* rehype-pretty-code — docs code blocks */
5449
.docs-prose [data-rehype-pretty-code-figure] {
@@ -80,21 +75,21 @@
8075
padding: 0 0.25rem;
8176
}
8277

83-
.docs-prose [data-rehype-pretty-code-figure] [data-rehype-pretty-code-title] {
84-
font-family: var(--font-mono), monospace;
85-
font-size: 0.7rem;
86-
color: var(--docs-code-title-fg);
87-
padding: 0.5rem 1.5rem;
88-
background: var(--docs-code-bg);
89-
border-bottom: 1px solid var(--docs-code-title-rule);
90-
border-radius: 0.75rem 0.75rem 0 0;
91-
}
78+
/* NOTE: the [data-rehype-pretty-code-title] rules were deleted — no code
79+
* fence in the repo uses the `title=` meta, so the element is never generated
80+
* (findings §9). Re-add title styling if a fence ever gains one; the
81+
* foreground for a dark title bar lives with the --docs-code-* constants. */
9282

93-
.docs-prose [data-rehype-pretty-code-figure]:has([data-rehype-pretty-code-title]) pre {
94-
border-radius: 0 0 0.75rem 0.75rem;
95-
}
9683

9784
.docs-prose :not(pre) > code {
85+
/* .docs-prose sets word-break:break-word, which split tokens like
86+
* @threadplane/langgraph into two separately-backgrounded pills mid-token.
87+
* Prefer moving the whole chip to the next line; break inside only when a
88+
* single token alone exceeds the line (findings §4). break-word, NOT
89+
* anywhere: `anywhere` also shrinks min-content to one character, which let
90+
* table columns squeeze below the chip width and wrap `agent` as agen/t. */
91+
word-break: normal;
92+
overflow-wrap: break-word;
9893
font-family: var(--font-mono), monospace;
9994
font-size: 0.85em;
10095
background: var(--color-accent-surface);
@@ -176,7 +171,30 @@
176171
.docs-prose > p:has(> .docs-diagram) { overflow-x: auto; }
177172
.docs-prose > p > img.docs-diagram { max-width: none; }
178173

179-
.docs-table-scroll { max-width: 100%; overflow-x: auto; margin: 1.5rem 0; }
174+
.docs-table-scroll {
175+
max-width: 100%;
176+
overflow-x: auto;
177+
margin: 1.5rem 0;
178+
/* Edge fades signal that the table scrolls; background-attachment:local
179+
* pins the covers to the content so they vanish at the ends. */
180+
background:
181+
linear-gradient(to right, var(--color-surface), var(--color-surface)) left / 24px 100%,
182+
linear-gradient(to right, var(--color-surface), var(--color-surface)) right / 24px 100%,
183+
linear-gradient(to right, rgba(0, 0, 0, 0.08), transparent) left / 16px 100%,
184+
linear-gradient(to left, rgba(0, 0, 0, 0.08), transparent) right / 16px 100%;
185+
background-repeat: no-repeat;
186+
background-attachment: local, local, scroll, scroll;
187+
}
188+
.docs-table-scroll:focus-visible {
189+
outline: none;
190+
box-shadow: var(--shadow-focus);
191+
border-radius: var(--radius-sm);
192+
}
193+
/* width:100% alone meant the table always fit its container, so the scroller
194+
* had nothing to scroll — at 375px the props table crushed `agent` into a
195+
* 49px column across three lines (findings §4). A floor makes narrow
196+
* viewports scroll instead of crush; wide viewports are unaffected. */
197+
.docs-table-scroll table { min-width: 560px; }
180198
.docs-prose table { width: 100%; border-collapse: collapse; font-size: 0.875rem; margin: 0; }
181199
.docs-prose th { text-align: left; padding: 0.5rem 0.75rem; font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase; color: var(--color-text-muted); border-bottom: 1px solid var(--color-accent-border); }
182200
.docs-prose td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--docs-accent-tint-soft); color: var(--color-text-secondary); }
@@ -455,6 +473,11 @@
455473
background: var(--color-border);
456474
margin-top: 4px;
457475
}
476+
/* The connector is per-step, so the last step trailed a dangling line into
477+
* the whitespace below (findings §7). */
478+
.mdx-step:last-child .mdx-step-connector {
479+
display: none;
480+
}
458481
.mdx-step-content {
459482
flex: 1;
460483
/* flex:1 leaves min-width:auto; the item refuses to shrink below its
@@ -934,11 +957,16 @@
934957
margin: 0;
935958
display: flex;
936959
flex-wrap: wrap;
937-
}
938-
.docs-crumb-link {
960+
align-items: center;
961+
row-gap: 4px;
962+
/* Typography on the LIST, not the links: the separators are siblings of the
963+
* links inside each li, and when only the links carried 13px the first two
964+
* separators inherited body's 16px/24px and floated 3px high (findings §3). */
939965
font-family: Inter, system-ui, sans-serif;
940966
font-size: 13px;
941967
line-height: 1.5;
968+
}
969+
.docs-crumb-link {
942970
color: var(--color-text-muted);
943971
text-decoration: none;
944972
}
@@ -947,9 +975,6 @@
947975
color: var(--color-text-muted);
948976
}
949977
.docs-crumb-current {
950-
font-family: Inter, system-ui, sans-serif;
951-
font-size: 13px;
952-
line-height: 1.5;
953978
text-decoration: none;
954979
color: var(--color-text-primary);
955980
font-weight: 600;

0 commit comments

Comments
 (0)