Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: highlight nav item in onPageNav ToC #1524

Merged

Conversation

tusharf5
Copy link
Contributor

@tusharf5 tusharf5 commented May 28, 2019

Motivation

Highlight nav item in onPageNav ToC when scrolling #1024

Have you read the Contributing Guidelines on pull requests?

Yes

Test Plan

Local Testing.

Before Changes - https://www.loom.com/share/956ba8b3696a41ba841d38fa5197ab20

After Changes - https://www.loom.com/share/68b57bf4af47400ab9abbdd1b8cbd3f6

Related PRs

#1024

@tusharf5 tusharf5 requested a review from endiliey as a code owner May 28, 2019 22:36
@facebook-github-bot facebook-github-bot added the CLA Signed Signed Facebook CLA label May 28, 2019
@docusaurus-bot
Copy link
Contributor

docusaurus-bot commented May 28, 2019

Deploy preview for docusaurus-2 ready!

Built with commit 4a0e0ae

https://deploy-preview-1524--docusaurus-2.netlify.com

@docusaurus-bot
Copy link
Contributor

docusaurus-bot commented May 28, 2019

Deploy preview for docusaurus-preview ready!

Built with commit 4a0e0ae

https://deploy-preview-1524--docusaurus-preview.netlify.com

Copy link
Contributor

@yangshun yangshun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I'm in favor of adding this feature but not sure whether it should be the default or opt-in. One argument against making it default is that this feature is not that useful on mobile and it'll be wasted bytes shipped to mobile clients. Anyway, few things that needs to be addressed before we can merge this:

  1. This PR does more than just "highlight nav item in onPageNav ToC", there's also scrolling to a heading when we click on the TOC. I don't think we want that behavior. The scrolling for certain items can take very long (although this probably can be configured); the browser default behavior of jumping directly to the heading is fine. For e.g. go to https://deploy-preview-1524--docusaurus-preview.netlify.com/docs/en/publishing#building-static-html-pages and click on "Publishing to GitHub Enterprise". It takes around a good 3s for it to scroll down and while the animation is nice, I think that takes far too long and is at the point of annoyance.

  2. Make the code ES5 friendly so that it works on older browsers hopefully (IE11).

  3. Fix some styling nits in the CSS.

@wgao19 @endilie have a look too. What do you all think?

packages/docusaurus-1.x/lib/core/Head.js Outdated Show resolved Hide resolved
packages/docusaurus-1.x/lib/core/Head.js Outdated Show resolved Hide resolved
packages/docusaurus-1.x/lib/static/css/main.css Outdated Show resolved Hide resolved
packages/docusaurus-1.x/lib/static/css/main.css Outdated Show resolved Hide resolved
packages/docusaurus-1.x/lib/static/js/scrollSpy.js Outdated Show resolved Hide resolved
packages/docusaurus-1.x/lib/static/js/scrollSpy.js Outdated Show resolved Hide resolved
packages/docusaurus-1.x/lib/static/js/scrollSpy.js Outdated Show resolved Hide resolved
@endiliey
Copy link
Contributor

endiliey commented May 29, 2019

Sorry but I’m not in favor of this PR.

First, it can be easily added by the user as a script. Katex did it (i can argue that the code is similar too) https://github.com/KaTeX/KaTeX/blob/master/website/static/js/scrollspy.js

Second, we are working on v2 and this means we have to port it back to v2. With such limited manpower (nobody is working on docusaurus full-time), its just going to delay v2 even more.

Third, new feature can come with a new bug. And eventually if bug arise, the maintainer will be the one having to fix it.

I think we need to make a clear stance that we are less likely to accept new feature as we are working on v2. Unless there is a high demand on it.

I really appreciate you taking your time to send this PR. I wish the effort was sent towards v2 instead

@wgao19
Copy link
Contributor

wgao19 commented May 29, 2019

I like this addition! Feels very natural to have the highlighting follow scrolling.

I agree with @yangshun in favor of the browser's default behavior. I'd say smooth scroll on header clicks is at most an opt-in.

Checked a few non-Docusaurus doc sites on this issue:

Doc site Highlight follows scroll Smooth scroll to header clicks
ReactJS No No
VueJS Yes Yes
Docz Yes No
Google Web Yes No

@tusharf5
Copy link
Contributor Author

Thank you all for the great feedback. @endiliey If this PR gets merged then I can certainly work on sending a PR that replicates this behavior in v2 also.

@endiliey
Copy link
Contributor

I'm going to let yall decide. My humble request and only complain is that we have to port this to v2 first before merging it. Not a good idea to see it in v1 but not in v2.

This was unexpected as well because there seems to be no discussion regarding this and suddenly the PR came out

@endiliey
Copy link
Contributor

Thank you all for the great feedback. @endiliey If this PR gets merged then I can certainly work on sending a PR that replicates this behavior in v2 also.

Oh cool, that'll be awesome then. Then my only complain is pretty much gone

@tusharf5
Copy link
Contributor Author

@yangshun I've made some changes according to the feedback.

  • Added a smoothScroll option in siteConfig to enable smooth scroll.
  • Combined the two scrollSpy scripts as one in ES5.
  • Update the documentation

Let me know what you think of this.

Copy link
Contributor

@yangshun yangshun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, we don't want the smooth scroll at all, only the highlighting of TOC when scrolling. Even if we want smooth scroll it should be a separate PR. This PR title doesn't accurately reflect the contents.

@tusharf5
Copy link
Contributor Author

@yangshun I've removed smooth scroll from this PR. Let me know if a separate PR for that would make sense : )

Copy link
Contributor

@yangshun yangshun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks better. Just a few more issues before we can merge it!

// Not visible. Scroll sidebar.
item.scrollIntoView({block: 'center', inline: 'nearest'});
// eslint-disable-next-line no-multi-assign
document.body.scrollTop = document.documentElement.scrollTop = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what these are for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized these lines were unnecessary so I've removed them.

@@ -725,7 +725,7 @@ blockquote {
position: fixed;
width: 100%;
z-index: 9999;
transform: translate3d(0,0,0);
transform: translate3d(0, 0, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing all these style inconsistencies, but we'd prefer to keep them out of this PR as it makes it harder to review (could make another PR to address styling issues).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this and one more.

@@ -172,6 +172,7 @@ class Head extends React.Component {
}}
/>
)}
<script src="/js/scrollSpy.js" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes a baseUrl of /, which is an incorrect assumption. See L186 where a similar script was added for the codetabs functionality.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return;
}
const bounding = item.getBoundingClientRect();
if (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand what this entire block does, do you mind explaining?

Also it's really uncommon to have an empty if block. It'd be better to negate the condition and shift the else into the negated if condition.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unnecessary code from here and also I've left a lot of comments and modified variable names to better understand what is going on. If it still doesn't make any sense I will be happy to explain it here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also trying to learn the chunk, here's my understanding, correct me if I'm wrong, and can consider the following comment?

(function scrollSpy() {
  const OFFSET = 10;
  let timer;
  let headingsCache;
  const findHeadings = function findHeadings() {
    return headingsCache || document.querySelectorAll('.toc-headings > li > a');
  };
  const onScroll = function onScroll() {
    if (timer) {
      // throttle
      return;
    }
    /**
     * On every call, try to find header right after  <-- next header
     * the one whose content is on the current screen <-- highlight this
     */
    timer = setTimeout(function() {
      timer = null;
      let activeNavFound = false;
      const headings = findHeadings(); // all of toc nav anchors
      for (let i = 0; i < headings.length; i++) {
        let currNavActive = !activeNavFound;
        /**
         * Enter the following check up only when an active nav header is not yet found
         * Then, check the bounding rectangle of the next header
         * The headers that are scrolled passed will have negative bounding rect top
         * So the first one with positive bounding rect top will be the nearest next header
         */
        if (currNavActive && i < headings.length - 1) {
          const next = headings[i + 1].href.split('#')[1];
          const nextHeader = document.getElementById(next);
          const top = nextHeader.getBoundingClientRect().top;
          currNavActive = top > OFFSET;
        }
        /**
         * Stop searching once a first such header is found,
         * this makes sure the highlighted header is the most current one
         */
        if (currNavActive) {
          activeNavFound = true;
          headings[i].classList.add('active');
        } else {
          headings[i].classList.remove('active');
        }
      }
    }, 100);
  };

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yupp that's correct. I will update the comments. Thank you :)

@tusharf5 tusharf5 force-pushed the feat-highlight-nav-item-on-pagenav-toc branch from 26bd209 to 71d1529 Compare May 30, 2019 12:31
Copy link
Contributor

@yangshun yangshun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, many thanks @tusharf5!

If you could try to add that functionality to v2 too that'll be nice

@yangshun yangshun merged commit 9514593 into facebook:master May 30, 2019
@tusharf5
Copy link
Contributor Author

Working on it. Will submit a PR soon 🙋‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Signed Facebook CLA
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants