diff --git a/packages/website/README.md b/packages/website/README.md index c7fb52b579..f4014f9555 100644 --- a/packages/website/README.md +++ b/packages/website/README.md @@ -78,7 +78,7 @@ TBD ## Docs -Docs are written in markdown and use Nextra. +Docs are written in markdown and uses [Nextra](https://nextra.vercel.app/). Notes - ensure that components (eg. `... `) are not indented diff --git a/packages/website/modules/docs-theme/toc/toc.js b/packages/website/modules/docs-theme/toc/toc.js index 0bedbfc066..adf20c26d5 100644 --- a/packages/website/modules/docs-theme/toc/toc.js +++ b/packages/website/modules/docs-theme/toc/toc.js @@ -1,4 +1,5 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useState, useRef } from 'react'; +import clsx from 'clsx'; import { ReactComponent as Chevron } from '../../../assets/icons/chevron.svg'; @@ -10,8 +11,9 @@ if (typeof window !== 'undefined') { export default function Toc() { const [isOpen, setOpen] = useState(false); const [nestedHeadings, setNestedHeadings] = useState([]); + const [updateKey, setUpdateKey] = useState(0); + const activeHeadings = useRef({}); let controller; - // const controller = new ScrollMagic.Controller(); const toggleClass = () => { setOpen(!isOpen); @@ -33,45 +35,68 @@ export default function Toc() { return str; }; + const updateHeadings = (id) => { + for (const element in activeHeadings.current) { + if (activeHeadings.current[element]) { + activeHeadings.current[element] = false; + } + } + activeHeadings.current[id] = true; + setUpdateKey(key => key + 1); + } + const getNestedHeadings = headingElements => { const nestedHeadings = []; + const headingIds = []; headingElements.forEach((heading, index) => { const id = string_to_slug(heading.innerText); const title = heading.innerText; + activeHeadings.current[id] = false; + headingIds.push(id); // add a[href] to headings heading.innerHTML = '' + title + ''; // store toc data if (heading.nodeName === 'H2') { nestedHeadings.push({ id, title, items: [] }); } else if (heading.nodeName === 'H3' && nestedHeadings.length > 0) { - nestedHeadings[nestedHeadings.length - 1].items.push({ - id, - title, - }); + nestedHeadings[nestedHeadings.length - 1].items.push({ id, title }); } + // scroll effects / add active class - new ScrollMagic.Scene({ triggerElement: `#${id}` }) - .on('enter leave', () => { - document.querySelectorAll('#toc a').forEach(el => { - el.classList.remove('active'); - }); - document.querySelector(`#toc a[href="#${id}"]`)?.classList.add('active'); - }) - .addTo(controller); + const exitScene = (e) => { + if (e.scrollDirection === 'REVERSE' && index !== 0) { + updateHeadings(headingIds[index - 1]); + } + } + + const scene = new ScrollMagic.Scene({ + triggerElement: `#${id}`, + triggerHook: 0.25, + duration: 200 + }).on('enter', () => { updateHeadings(id) }).addTo(controller); + scene.on('leave', exitScene).addTo(controller); }); return nestedHeadings; }; const Headings = ({ headings }) => (