Skip to content

Commit

Permalink
✨ optimize jump experience of TOC (#9)
Browse files Browse the repository at this point in the history
* feat: ✨ optimize jump experience of TOC

* feat: add the offset back when header is hidden

---------

Co-authored-by: StarHeartHunt <[email protected]>
  • Loading branch information
yixiaojiu and StarHeartHunt authored May 12, 2024
1 parent 1d3ad6c commit aec6a00
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/preset-nonepress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
},
"repository": {
"type": "git",
"url": "git+https://github.com/nonebot/docusaurus-preset-nonepress.git",
"url": "https://github.com/nonebot/docusaurus-theme-nonepress.git",
"directory": "packages/preset-nonepress"
},
"license": "MIT",
Expand Down
38 changes: 37 additions & 1 deletion packages/theme-nonepress/src/theme/TOC/Tree/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,56 @@
import React from "react";
import React, { useCallback } from "react";

import clsx from "clsx";

import type { Props } from "@theme/TOC/Tree";

const OFFSET = 70;

// Recursive component rendering the toc tree
function TOCTree({ toc, linkClassName }: Props): JSX.Element | null {
const handleClick = useCallback(
(event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
const eventTarget = event.currentTarget;
const targetEl = document.getElementById(
decodeURIComponent(eventTarget.href.split("#")[1]),
);
if (!targetEl) {
return;
}
const targetPadding = parseInt(
window.getComputedStyle(targetEl).paddingTop,
10,
);
let targetTop =
window.scrollY +
targetEl.getBoundingClientRect().top -
OFFSET +
targetPadding;

// if scrolling down to the target, the header is hidden
// so add back the offset for the header
if (targetTop > window.scrollY) targetTop += OFFSET;

requestAnimationFrame(() => {
if (Math.abs(targetTop - window.scrollY) > window.innerHeight)
window.scrollTo(0, targetTop);
else window.scrollTo({ left: 0, top: targetTop, behavior: "smooth" });
});
},
[],
);
if (!toc.length) {
return null;
}

return (
<ul className="toc-tree">
{toc.map((heading) => (
<li key={heading.id}>
<a
href={`#${heading.id}`}
onClick={handleClick}
className={clsx("menu-link menu-item", linkClassName)}
>
{/* Developer provided the HTML, so assume it's safe. */}
Expand Down

0 comments on commit aec6a00

Please sign in to comment.