diff --git a/CHANGELOG-2.x.md b/CHANGELOG-2.x.md index 5f2661f3b983..999e9334c482 100644 --- a/CHANGELOG-2.x.md +++ b/CHANGELOG-2.x.md @@ -2,11 +2,14 @@ ## Unreleased +- Add table of contents highlighting on scroll. + ## 2.0.0-alpha.32 ### Features -- Add `` component for easy client side redirect. -Example Usage: + +- Add `` component for easy client side redirect. Example Usage: + ```js import React from 'react'; import {Redirect} from '@docusaurus/router'; @@ -15,19 +18,21 @@ function Home() { return ; } ``` + - Allow user to add custom HTML to footer items. [#1905](https://github.com/facebook/docusaurus/pull/1905) -- Added code block line highlighting feature (thanks @lex111)! If you have previously swizzled the `CodeBlock` theme component, it is recommended to update your source code to have this feature. -([#1860](https://github.com/facebook/Docusaurus/issues/1860)) +- Added code block line highlighting feature (thanks @lex111)! If you have previously swizzled the `CodeBlock` theme component, it is recommended to update your source code to have this feature. ([#1860](https://github.com/facebook/Docusaurus/issues/1860)) ### Bug Fixes + - Fix `@theme/Tabs` component to be able to create tabs with only one item. - Fix MDX `@theme/Heading` component. If there is no id, it should not create anchor link. -- Fixed a bug in which if `themeConfig.algolia` is not defined, the custom searchbar won't appear. -If you've swizzled Algolia `SearchBar` component before, please update your source code otherwise CSS might break. See [#1909](https://github.com/facebook/docusaurus/pull/1909/files) for reference. +- Fixed a bug in which if `themeConfig.algolia` is not defined, the custom searchbar won't appear. If you've swizzled Algolia `SearchBar` component before, please update your source code otherwise CSS might break. See [#1909](https://github.com/facebook/docusaurus/pull/1909/files) for reference. + ```js - +
``` + - Slightly adjust search icon position to be more aligned on small width device. ([#1893](https://github.com/facebook/Docusaurus/issues/1893)) - Fix algolia styling bug, previously search suggestion result is sometimes hidden. ([#1915](https://github.com/facebook/Docusaurus/issues/1915)) - Changed the way we read the `USE_SSH` env variable during deployment to be the same as in v1. @@ -36,12 +41,13 @@ If you've swizzled Algolia `SearchBar` component before, please update your sour - Fix a bug where docs plugin add `/docs` route even if docs folder is empty. We also improved docs plugin test coverage to 100% for stability before working on docs versioning. ([#1912](https://github.com/facebook/Docusaurus/issues/1912)) ### Performance Improvement + - Reduce memory usage consumption. ([#1900](https://github.com/facebook/Docusaurus/issues/1900)) - Significantly reduce main bundle size and initial HTML payload on production build. Generated files from webpack is also shorter in name. ([#1898](https://github.com/facebook/Docusaurus/issues/1898)) -- Simplify blog metadata. Previously, accessing `/blog/post-xxx` will request for next and prev blog post metadata too aside from target post metadata. We should only request target post metadata. -([#1908](https://github.com/facebook/Docusaurus/issues/1908)) +- Simplify blog metadata. Previously, accessing `/blog/post-xxx` will request for next and prev blog post metadata too aside from target post metadata. We should only request target post metadata. ([#1908](https://github.com/facebook/Docusaurus/issues/1908)) ### Others + - Convert sitemap plugin to TypeScript. ([#1894](https://github.com/facebook/Docusaurus/issues/1894)) - Refactor dark mode toggle into a hook. ([#1899](https://github.com/facebook/Docusaurus/issues/1899)) diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/index.js b/packages/docusaurus-theme-classic/src/theme/DocItem/index.js index eeb7cfc311ed..5678f93299bf 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/index.js +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/index.js @@ -11,16 +11,23 @@ import Head from '@docusaurus/Head'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useBaseUrl from '@docusaurus/useBaseUrl'; import DocPaginator from '@theme/DocPaginator'; +import useTOCHighlight from '@theme/hooks/useTOCHighlight'; import styles from './styles.module.css'; +const LINK_CLASS_NAME = 'contents__link'; +const ACTIVE_LINK_CLASS_NAME = 'contents__link--active'; +const TOP_OFFSET = 100; + function Headings({headings, isChild}) { + useTOCHighlight(LINK_CLASS_NAME, ACTIVE_LINK_CLASS_NAME, TOP_OFFSET); + if (!headings.length) return null; return (
    {headings.map(heading => (
  • - + {heading.value} diff --git a/packages/docusaurus-theme-classic/src/theme/Navbar/index.js b/packages/docusaurus-theme-classic/src/theme/Navbar/index.js index 77f9211c17f9..5919bd401e9a 100644 --- a/packages/docusaurus-theme-classic/src/theme/Navbar/index.js +++ b/packages/docusaurus-theme-classic/src/theme/Navbar/index.js @@ -17,7 +17,7 @@ import SearchBar from '@theme/SearchBar'; import classnames from 'classnames'; -import useTheme from '@theme/hooks/theme'; +import useTheme from '@theme/hooks/useTheme'; import styles from './styles.module.css'; diff --git a/packages/docusaurus-theme-classic/src/theme/hooks/useTOCHighlight.js b/packages/docusaurus-theme-classic/src/theme/hooks/useTOCHighlight.js new file mode 100644 index 000000000000..bd033925b8c4 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/hooks/useTOCHighlight.js @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {useEffect, useState} from 'react'; + +function useTOCHighlight(linkClassName, linkActiveClassName, topOffset) { + const [lastActiveLink, setLastActiveLink] = useState(undefined); + + useEffect(() => { + let headersAnchors = []; + let links = []; + + function setActiveLink() { + function getActiveHeaderAnchor() { + let index = 0; + let activeHeaderAnchor = null; + + headersAnchors = document.getElementsByClassName('anchor'); + while (index < headersAnchors.length && !activeHeaderAnchor) { + const headerAnchor = headersAnchors[index]; + const {top} = headerAnchor.getBoundingClientRect(); + + if (top >= 0 && top <= topOffset) { + activeHeaderAnchor = headerAnchor; + } + + index += 1; + } + + return activeHeaderAnchor; + } + + const activeHeaderAnchor = getActiveHeaderAnchor(); + + if (activeHeaderAnchor) { + let index = 0; + let itemHighlighted = false; + + links = 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; + } + } + } + + document.addEventListener('scroll', setActiveLink); + document.addEventListener('resize', setActiveLink); + + setActiveLink(); + + return () => { + document.removeEventListener('scroll', setActiveLink); + document.removeEventListener('resize', setActiveLink); + }; + }); +} + +export default useTOCHighlight; diff --git a/packages/docusaurus-theme-classic/src/theme/hooks/theme.js b/packages/docusaurus-theme-classic/src/theme/hooks/useTheme.js similarity index 100% rename from packages/docusaurus-theme-classic/src/theme/hooks/theme.js rename to packages/docusaurus-theme-classic/src/theme/hooks/useTheme.js