feat(v2): hide navbar on scroll (#2055)

* feat(v2): hide navbar on scroll

* Turn on hide option

* Refactor after review
This commit is contained in:
Alexey Pyltsyn 2019-12-12 15:19:37 +03:00 committed by Yangshun Tay
parent ace93c5a14
commit 5bfa5d6579
5 changed files with 92 additions and 4 deletions

View file

@ -17,6 +17,7 @@ import Toggle from '@theme/Toggle';
import classnames from 'classnames'; import classnames from 'classnames';
import useTheme from '@theme/hooks/useTheme'; import useTheme from '@theme/hooks/useTheme';
import useHideableNavbar from '@theme/hooks/useHideableNavbar';
import styles from './styles.module.css'; import styles from './styles.module.css';
@ -43,13 +44,15 @@ function NavLink({to, href, label, position, ...props}) {
function Navbar() { function Navbar() {
const context = useDocusaurusContext(); const context = useDocusaurusContext();
const [sidebarShown, setSidebarShown] = useState(false);
const [isSearchBarExpanded, setIsSearchBarExpanded] = useState(false);
const [theme, setTheme] = useTheme();
const {siteConfig = {}} = context; const {siteConfig = {}} = context;
const {baseUrl, themeConfig = {}} = siteConfig; const {baseUrl, themeConfig = {}} = siteConfig;
const {navbar = {}, disableDarkMode = false} = themeConfig; const {navbar = {}, disableDarkMode = false} = themeConfig;
const {title, logo = {}, links = []} = navbar; const {title, logo = {}, links = [], hideOnScroll = false} = navbar;
const [sidebarShown, setSidebarShown] = useState(false);
const [isSearchBarExpanded, setIsSearchBarExpanded] = useState(false);
const [theme, setTheme] = useTheme();
const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
const showSidebar = useCallback(() => { const showSidebar = useCallback(() => {
setSidebarShown(true); setSidebarShown(true);
@ -71,8 +74,11 @@ function Navbar() {
<html lang="en" data-theme={theme} /> <html lang="en" data-theme={theme} />
</Head> </Head>
<nav <nav
ref={navbarRef}
className={classnames('navbar', 'navbar--light', 'navbar--fixed-top', { className={classnames('navbar', 'navbar--light', 'navbar--fixed-top', {
'navbar-sidebar--show': sidebarShown, 'navbar-sidebar--show': sidebarShown,
[styles.navbarHideable]: hideOnScroll,
[styles.navbarHidden]: !isNavbarVisible,
})}> })}>
<div className="navbar__inner"> <div className="navbar__inner">
<div className="navbar__items"> <div className="navbar__items">

View file

@ -16,3 +16,11 @@
display: none; display: none;
} }
} }
.navbarHideable {
transition: top 0.2s ease-in-out;
}
.navbarHidden {
top: calc(var(--ifm-navbar-height) * -1) !important;
}

View file

@ -0,0 +1,56 @@
/**
* 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 React, {useState, useCallback, useEffect} from 'react'; // eslint-disable-line no-unused-vars
const useHideableNavbar = hideOnScroll => {
const [isNavbarVisible, setIsNavbarVisible] = useState(true);
const [lastScrollTop, setLastScrollTop] = useState(0);
const [navbarHeight, setNavbarHeight] = useState(0);
const navbarRef = useCallback(node => {
if (node !== null) {
setNavbarHeight(node.getBoundingClientRect().height);
}
}, []);
const handleScroll = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const documentHeight = document.documentElement.scrollHeight - navbarHeight;
const windowHeight = window.innerHeight;
if (scrollTop < navbarHeight) {
return;
}
if (lastScrollTop && scrollTop > lastScrollTop) {
setIsNavbarVisible(false);
} else if (scrollTop + windowHeight < documentHeight) {
setIsNavbarVisible(true);
}
setLastScrollTop(scrollTop);
};
useEffect(() => {
if (!hideOnScroll) {
return undefined;
}
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [lastScrollTop, navbarHeight]);
return {
navbarRef,
isNavbarVisible,
};
};
export default useHideableNavbar;

View file

@ -90,6 +90,23 @@ module.exports = {
Outbound links automatically get `target="_blank" rel="noopener noreferrer"`. Outbound links automatically get `target="_blank" rel="noopener noreferrer"`.
### Auto-hide sticky navbar
You can enable this cool UI feature that automatically hides the navbar when a user starts scrolling down the page, and show it again when the user scrolls up.
```js
// docusaurus/config.js
module.exports = {
...
themeConfig: {
navbar: {
hideOnScroll: true,
},
...
},
}
```
## Footer ## Footer
## `CodeBlock` ## `CodeBlock`

View file

@ -74,6 +74,7 @@ module.exports = {
}, },
}, },
navbar: { navbar: {
hideOnScroll: true,
title: 'Docusaurus', title: 'Docusaurus',
logo: { logo: {
alt: 'Docusaurus Logo', alt: 'Docusaurus Logo',