Skip to content

Commit 6b1017c

Browse files
authored
fix: make TOC rendering consistent regardless of the page content (#1189)
Sets `flex-wrap: nowrap` to allow for "overflowing" TOC when too wide. Swizzles the `TOCItems` component into `@apify/docs-theme`. Uses a [hack](https://stackoverflow.com/questions/556153/inline-elements-shifting-when-made-bold-on-hover) with `::before` pseudoclass to reserve space for the bold TOC items, so the element width doesn't change on selection. Closes #1188
1 parent 1b68c64 commit 6b1017c

File tree

7 files changed

+115
-6
lines changed

7 files changed

+115
-6
lines changed

apify-docs-theme/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"access": "public"
2020
},
2121
"dependencies": {
22-
"@apify/docs-search-modal": "^1.1.0",
22+
"@apify/docs-search-modal": "^1.1.1",
2323
"@docusaurus/theme-common": "^3.5.2",
2424
"@stackql/docusaurus-plugin-hubspot": "^1.1.0",
2525
"axios": "^1.7.4",
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import Link from '@docusaurus/Link';
2+
import clsx from 'clsx';
3+
import React from 'react';
4+
5+
import styles from './styles.module.css';
6+
7+
// Recursive component rendering the toc tree
8+
function TOCItemTree({
9+
toc,
10+
className,
11+
linkClassName,
12+
isChild,
13+
}) {
14+
if (!toc.length) {
15+
return null;
16+
}
17+
return (
18+
<ul className={isChild ? undefined : className}>
19+
{toc.map((heading) => (
20+
<li key={heading.id}>
21+
<Link
22+
to={`#${heading.id}`}
23+
className={clsx(styles.apifyTocLink, linkClassName ?? undefined)}
24+
data-label={heading.value}
25+
// Developer provided the HTML, so assume it's safe.
26+
dangerouslySetInnerHTML={{ __html: heading.value }}
27+
/>
28+
<TOCItemTree
29+
isChild
30+
toc={heading.children}
31+
className={className}
32+
linkClassName={linkClassName}
33+
/>
34+
</li>
35+
))}
36+
</ul>
37+
);
38+
}
39+
40+
// Memo only the tree root is enough
41+
export default React.memo(TOCItemTree);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useThemeConfig } from '@docusaurus/theme-common';
2+
import {
3+
useTOCHighlight,
4+
useFilteredAndTreeifiedTOC,
5+
} from '@docusaurus/theme-common/internal';
6+
import TOCItemTree from '@theme/TOCItems/Tree';
7+
import React, { useMemo } from 'react';
8+
9+
export default function TOCItems({
10+
toc,
11+
className = 'table-of-contents table-of-contents__left-border',
12+
linkClassName = 'table-of-contents__link',
13+
linkActiveClassName = undefined,
14+
minHeadingLevel: minHeadingLevelOption,
15+
maxHeadingLevel: maxHeadingLevelOption,
16+
...props
17+
}) {
18+
const themeConfig = useThemeConfig();
19+
20+
const minHeadingLevel = minHeadingLevelOption ?? themeConfig.tableOfContents.minHeadingLevel;
21+
const maxHeadingLevel = maxHeadingLevelOption ?? themeConfig.tableOfContents.maxHeadingLevel;
22+
23+
const tocTree = useFilteredAndTreeifiedTOC({
24+
toc,
25+
minHeadingLevel,
26+
maxHeadingLevel,
27+
});
28+
29+
const tocHighlightConfig = useMemo(() => {
30+
if (linkClassName && linkActiveClassName) {
31+
return {
32+
linkClassName,
33+
linkActiveClassName,
34+
minHeadingLevel,
35+
maxHeadingLevel,
36+
};
37+
}
38+
return undefined;
39+
}, [linkClassName, linkActiveClassName, minHeadingLevel, maxHeadingLevel]);
40+
useTOCHighlight(tocHighlightConfig);
41+
42+
return (
43+
<TOCItemTree
44+
toc={tocTree}
45+
className={className}
46+
linkClassName={linkClassName}
47+
{...props}
48+
/>
49+
);
50+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.apifyTocLink {
2+
display: block;
3+
}
4+
5+
.apifyTocLink::before {
6+
display: block;
7+
content: attr(data-label);
8+
font-weight: 700;
9+
height: 0;
10+
overflow: hidden;
11+
visibility: hidden;
12+
}

package-lock.json

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/theme/DocItem/Layout/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export default function DocItemLayout({ children }) {
7474
);
7575
return (
7676
<div
77-
className="row">
77+
className={clsx('row', styles.row)}>
7878
<div
7979
className={clsx('col', !docTOC.hidden && styles.docItemCol)}>
8080
<DocVersionBanner/>

src/theme/DocItem/Layout/styles.module.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@
2121
.docItemCol {
2222
max-width: 820px !important;
2323
}
24-
}
24+
}
25+
26+
.row {
27+
flex-wrap: nowrap;
28+
}

0 commit comments

Comments
 (0)