Skip to content

Commit 91d0864

Browse files
committed
Enhance Toc component with optimistic scrolling and transition handling
1 parent d50cbcd commit 91d0864

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

src/components/Layout/Toc.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,32 @@
1010
*/
1111

1212
import cx from 'classnames';
13+
import {startTransition, useOptimistic} from 'react';
1314
import {useTocHighlight} from './useTocHighlight';
1415
import {IsInTocContext} from '../MDX/TocContext';
1516
import type {Toc} from '../MDX/TocContext';
1617

18+
function waitForScrollEnd(): Promise<void> {
19+
return new Promise((resolve) => {
20+
let settled = false;
21+
const finish = () => {
22+
if (settled) return;
23+
settled = true;
24+
window.removeEventListener('scrollend', finish);
25+
resolve();
26+
};
27+
window.addEventListener('scrollend', finish, {once: true});
28+
setTimeout(finish, 1000);
29+
});
30+
}
31+
1732
export function Toc({headings}: {headings: Toc}) {
1833
const {currentIndex} = useTocHighlight();
34+
const [optimisticIndex, setOptimisticIndex] = useOptimistic(currentIndex);
1935
// TODO: We currently have a mismatch between the headings in the document
2036
// and the headings we find in MarkdownPage (i.e. we don't find Recap or Challenges).
2137
// Select the max TOC item we have here for now, but remove this after the fix.
22-
const selectedIndex = Math.min(currentIndex, headings.length - 1);
38+
const selectedIndex = Math.min(optimisticIndex, headings.length - 1);
2339
return (
2440
<nav role="navigation" className="pt-20 sticky top-0 end-0">
2541
{headings.length > 0 && (
@@ -59,7 +75,13 @@ export function Toc({headings}: {headings: Toc}) {
5975
: 'text-secondary dark:text-secondary-dark',
6076
'block hover:text-link dark:hover:text-link-dark leading-normal py-2'
6177
)}
62-
href={h.url}>
78+
href={h.url}
79+
onClick={() => {
80+
startTransition(async () => {
81+
setOptimisticIndex(i);
82+
await waitForScrollEnd();
83+
});
84+
}}>
6385
{h.text}
6486
</a>
6587
</li>

0 commit comments

Comments
 (0)