diff --git a/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx b/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx index 4daaebf30c..272a71f150 100644 --- a/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Heading/index.tsx @@ -48,7 +48,7 @@ const createAnchorHeading = ( tags. - const links: HTMLCollectionOf = document.getElementsByClassName( - linkClassName, - ); - while (index < links.length && !itemHighlighted) { - const link = links[index]; - const {href} = link; - const anchorValue = decodeURIComponent( - href.substring(href.indexOf('#') + 1), - ); - - if (activeHeaderAnchor.id === anchorValue) { - if (lastActiveLink) { - lastActiveLink.classList.remove(linkActiveClassName); - } - link.classList.add(linkActiveClassName); - setLastActiveLink(link); - itemHighlighted = true; - } - - index += 1; + function updateLinkActiveClass(link: HTMLAnchorElement, active: boolean) { + if (active) { + if (lastActiveLinkRef.current && lastActiveLinkRef.current !== link) { + lastActiveLinkRef.current?.classList.remove(linkActiveClassName); } + link.classList.add(linkActiveClassName); + lastActiveLinkRef.current = link; + } else { + link.classList.remove(linkActiveClassName); } } - document.addEventListener('scroll', setActiveLink); - document.addEventListener('resize', setActiveLink); + function updateActiveLink() { + const links = getLinks(linkClassName); + const activeAnchor = getActiveAnchor(); + const activeLink = links.find( + (link) => activeAnchor && activeAnchor.id === getLinkAnchorValue(link), + ); - setActiveLink(); + links.forEach((link) => { + updateLinkActiveClass(link, link === activeLink); + }); + } + + document.addEventListener('scroll', updateActiveLink); + document.addEventListener('resize', updateActiveLink); + + updateActiveLink(); return () => { - document.removeEventListener('scroll', setActiveLink); - document.removeEventListener('resize', setActiveLink); + document.removeEventListener('scroll', updateActiveLink); + document.removeEventListener('resize', updateActiveLink); }; - }); + }, [params]); } export default useTOCHighlight; diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts index 22f3be8d39..94f1781050 100644 --- a/packages/docusaurus-theme-classic/src/types.d.ts +++ b/packages/docusaurus-theme-classic/src/types.d.ts @@ -255,11 +255,11 @@ declare module '@theme/hooks/useThemeContext' { } declare module '@theme/hooks/useTOCHighlight' { - export default function useTOCHighlight( - linkClassName: string, - linkActiveClassName: string, - topOffset: number, - ): void; + export type Params = { + linkClassName: string; + linkActiveClassName: string; + }; + export default function useTOCHighlight(params: Params): void; } declare module '@theme/hooks/useUserPreferencesContext' {