Skip to content

Commit

Permalink
fix(v2): enable scrolling for sidebar menu only (#2645)
Browse files Browse the repository at this point in the history
* fix(v2): enable scrolling for sidebar menu only

* Add support for announcement bar

* fix: remove redundant styles
  • Loading branch information
lex111 authored May 25, 2020
1 parent 34e664a commit d391a2b
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,23 @@
* LICENSE file in the root directory of this source tree.
*/

import React, {useState, useEffect} from 'react';
import React from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useAnnouncementBarContext from '@theme/hooks/useAnnouncementBarContext';

import styles from './styles.module.css';

const STORAGE_DISMISS_KEY = 'docusaurus.announcement.dismiss';
const STORAGE_ID_KEY = 'docusaurus.announcement.id';

function AnnouncementBar() {
const {
siteConfig: {themeConfig: {announcementBar = {}}} = {},
} = useDocusaurusContext();
const {id, content, backgroundColor, textColor} = announcementBar;
const [isClosed, setClosed] = useState(true);
const handleClose = () => {
localStorage.setItem(STORAGE_DISMISS_KEY, true);
setClosed(true);
};

useEffect(() => {
const viewedId = localStorage.getItem(STORAGE_ID_KEY);
const isNewAnnouncement = id !== viewedId;

localStorage.setItem(STORAGE_ID_KEY, id);

if (isNewAnnouncement) {
localStorage.setItem(STORAGE_DISMISS_KEY, false);
}

if (
isNewAnnouncement ||
localStorage.getItem(STORAGE_DISMISS_KEY) === 'false'
) {
setClosed(false);
}
}, []);
const {content, backgroundColor, textColor} = announcementBar;
const {
isAnnouncementBarClosed,
closeAnnouncementBar,
} = useAnnouncementBarContext();

if (!content || isClosed) {
if (!content || isAnnouncementBarClosed) {
return null;
}

Expand All @@ -59,7 +38,7 @@ function AnnouncementBar() {
<button
type="button"
className={styles.announcementBarClose}
onClick={handleClose}
onClick={closeAnnouncementBar}
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,24 @@
* LICENSE file in the root directory of this source tree.
*/

:root {
--docusaurus-announcement-bar-height: auto;
}

.announcementBar {
position: relative;
width: 100%;
height: var(--docusaurus-announcement-bar-height);
background-color: var(--ifm-color-primary);
color: var(--ifm-color-black);
}

@media screen and (min-width: 1024px) {
:root {
--docusaurus-announcement-bar-height: 30px;
}
}

.announcementBarClose {
position: absolute;
right: 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {createContext} from 'react';

const AnnouncementBarContext = createContext({
isAnnouncementBarClosed: false,
closeAnnouncementBar: () => {},
});

export default AnnouncementBarContext;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';

import AnnouncementBarContext from '@theme/AnnouncementBarContext';
import useAnnouncementBar from '@theme/hooks/useAnnouncementBar';

function AnnouncementBarProvider(props) {
const {isAnnouncementBarClosed, closeAnnouncementBar} = useAnnouncementBar();

return (
<AnnouncementBarContext.Provider
value={{isAnnouncementBarClosed, closeAnnouncementBar}}>
{props.children}
</AnnouncementBarContext.Provider>
);
}

export default AnnouncementBarProvider;
11 changes: 10 additions & 1 deletion packages/docusaurus-theme-classic/src/theme/DocSidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import React, {useState, useCallback} from 'react';
import classnames from 'classnames';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useAnnouncementBarContext from '@theme/hooks/useAnnouncementBarContext';
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
import useLogo from '@theme/hooks/useLogo';
import useScrollPosition from '@theme/hooks/useScrollPosition';
import Link from '@docusaurus/Link';
import isInternalUrl from '@docusaurus/isInternalUrl';

Expand Down Expand Up @@ -134,6 +136,8 @@ function DocSidebar(props) {
isClient,
} = useDocusaurusContext();
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
const {isAnnouncementBarClosed} = useAnnouncementBarContext();
const {scrollY} = useScrollPosition();

const {
docsSidebars,
Expand Down Expand Up @@ -163,7 +167,10 @@ function DocSidebar(props) {
}

return (
<div className={styles.sidebar}>
<div
className={classnames(styles.sidebar, {
[styles.sidebarWithHideableNavbar]: hideOnScroll,
})}>
{hideOnScroll && (
<Link
tabIndex="-1"
Expand All @@ -179,6 +186,8 @@ function DocSidebar(props) {
<div
className={classnames('menu', 'menu--responsive', styles.menu, {
'menu--show': showResponsiveSidebar,
[styles.menuWithAnnouncementBar]:
!isAnnouncementBarClosed && scrollY === 0,
})}>
<button
aria-label={showResponsiveSidebar ? 'Close Menu' : 'Open Menu'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@

@media (min-width: 997px) {
.sidebar {
display: flex;
flex-direction: column;
height: 100vh;
overflow-y: auto;
position: sticky;
top: 0;
padding-top: var(--ifm-navbar-height);
}

.sidebarWithHideableNavbar {
padding-top: 0;
}

.sidebar::-webkit-scrollbar {
width: 7px;
}
Expand All @@ -35,10 +41,9 @@
.sidebarLogo {
display: flex !important;
align-items: center;
position: absolute;
top: 0;
margin: 0 var(--ifm-navbar-padding-horizontal);
height: var(--ifm-navbar-height);
min-height: var(--ifm-navbar-height);
max-height: var(--ifm-navbar-height);
color: inherit !important;
text-decoration: none !important;
}
Expand All @@ -49,8 +54,13 @@
}

.menu {
flex-grow: 1;
padding: 0.5rem;
}

.menuWithAnnouncementBar {
margin-bottom: var(--docusaurus-announcement-bar-height);
}
}

.sidebarLogo {
Expand Down
68 changes: 37 additions & 31 deletions packages/docusaurus-theme-classic/src/theme/Layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl';

import ThemeProvider from '@theme/ThemeProvider';
import TabGroupChoiceProvider from '@theme/TabGroupChoiceProvider';
import AnnouncementBarProvider from '@theme/AnnouncementBarProvider';
import AnnouncementBar from '@theme/AnnouncementBar';
import Navbar from '@theme/Navbar';
import Footer from '@theme/Footer';
Expand Down Expand Up @@ -50,38 +51,43 @@ function Layout(props) {
return (
<ThemeProvider>
<TabGroupChoiceProvider>
<Head>
{/* TODO: Do not assume that it is in english language */}
<html lang="en" />
<AnnouncementBarProvider>
<Head>
{/* TODO: Do not assume that it is in english language */}
<html lang="en" />

{metaTitle && <title>{metaTitle}</title>}
{metaTitle && <meta property="og:title" content={metaTitle} />}
{favicon && <link rel="shortcut icon" href={faviconUrl} />}
{description && <meta name="description" content={description} />}
{description && (
<meta property="og:description" content={description} />
)}
{version && <meta name="docsearch:version" content={version} />}
{keywords && keywords.length && (
<meta name="keywords" content={keywords.join(',')} />
)}
{metaImage && <meta property="og:image" content={metaImageUrl} />}
{metaImage && (
<meta property="twitter:image" content={metaImageUrl} />
)}
{metaImage && (
<meta name="twitter:image:alt" content={`Image for ${metaTitle}`} />
)}
{permalink && (
<meta property="og:url" content={siteUrl + permalink} />
)}
{permalink && <link rel="canonical" href={siteUrl + permalink} />}
<meta name="twitter:card" content="summary_large_image" />
</Head>
<AnnouncementBar />
<Navbar />
<div className="main-wrapper">{children}</div>
{!noFooter && <Footer />}
{metaTitle && <title>{metaTitle}</title>}
{metaTitle && <meta property="og:title" content={metaTitle} />}
{favicon && <link rel="shortcut icon" href={faviconUrl} />}
{description && <meta name="description" content={description} />}
{description && (
<meta property="og:description" content={description} />
)}
{version && <meta name="docsearch:version" content={version} />}
{keywords && keywords.length && (
<meta name="keywords" content={keywords.join(',')} />
)}
{metaImage && <meta property="og:image" content={metaImageUrl} />}
{metaImage && (
<meta property="twitter:image" content={metaImageUrl} />
)}
{metaImage && (
<meta
name="twitter:image:alt"
content={`Image for ${metaTitle}`}
/>
)}
{permalink && (
<meta property="og:url" content={siteUrl + permalink} />
)}
{permalink && <link rel="canonical" href={siteUrl + permalink} />}
<meta name="twitter:card" content="summary_large_image" />
</Head>
<AnnouncementBar />
<Navbar />
<div className="main-wrapper">{children}</div>
{!noFooter && <Footer />}
</AnnouncementBarProvider>
</TabGroupChoiceProvider>
</ThemeProvider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {useState, useEffect} from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';

const STORAGE_DISMISS_KEY = 'docusaurus.announcement.dismiss';
const STORAGE_ID_KEY = 'docusaurus.announcement.id';

const useAnnouncementBar = () => {
const {
siteConfig: {
themeConfig: {
announcementBar: {id},
},
} = {},
} = useDocusaurusContext();
const [isClosed, setClosed] = useState(true);
const handleClose = () => {
localStorage.setItem(STORAGE_DISMISS_KEY, true);
setClosed(true);
};

useEffect(() => {
const viewedId = localStorage.getItem(STORAGE_ID_KEY);
const isNewAnnouncement = id !== viewedId;

localStorage.setItem(STORAGE_ID_KEY, id);

if (isNewAnnouncement) {
localStorage.setItem(STORAGE_DISMISS_KEY, false);
}

if (
isNewAnnouncement ||
localStorage.getItem(STORAGE_DISMISS_KEY) === 'false'
) {
setClosed(false);
}
}, []);

return {
isAnnouncementBarClosed: isClosed,
closeAnnouncementBar: handleClose,
};
};

export default useAnnouncementBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {useContext} from 'react';
import AnnouncementBarContext from '@theme/AnnouncementBarContext';

function useAnnouncementBarContext() {
return useContext(AnnouncementBarContext);
}

export default useAnnouncementBarContext;

0 comments on commit d391a2b

Please sign in to comment.