mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 18:27:56 +02:00
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:
parent
ace93c5a14
commit
5bfa5d6579
5 changed files with 92 additions and 4 deletions
|
@ -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">
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
|
@ -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`
|
||||||
|
|
|
@ -74,6 +74,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
|
hideOnScroll: true,
|
||||||
title: 'Docusaurus',
|
title: 'Docusaurus',
|
||||||
logo: {
|
logo: {
|
||||||
alt: 'Docusaurus Logo',
|
alt: 'Docusaurus Logo',
|
||||||
|
|
Loading…
Add table
Reference in a new issue