feat(v2): bootstrap doc sidebar (#2735)

* feat(v2): add minor adjustements and footer component

* fix(v2): margin and spacing of footer

* feat(v2): add navbar component

* ádd collapse classname

* feat(v2): add dependencies

* feat(v2): remove unused code

* feat(v2): remove unused links

* feat(v2): add reactstrap components :|

* feat(v2): add brand and other nav componnets

* feat(v2): Add the layout tag

* feat(v2): bootstrap start doc components

* feat(v2: Add syntax highlight

* Ádd Page components

* feat(v2): Bootstrap MDX Componnets

* fix(v2): Fix layout height

* fix(v2): Fix spacings

* feat:(v2): Add the layout in doc content

* feat(v2): Start the pagination

* feat(v2): Finish pagination

* Fix margins in mobile

* feat(v2): Add the doc sidebar

* feat(v2): Add sidebar

* feat(v2): Makes sidebar responsive

* feat(v2): Add context

* feat(v2): Add new hook and docs to the template sidebar

* feat(v2): Add css modules

* feat(v2): add sidebar class

* feat(v2): add floating action button

* fix fab styles

* fix(v2): fix height

* feat(v2): Remove context

* feat(v2): Finish sidebar

* feat(v2): Add resize window hook

* feat(v2): Remove unsed fields

* feat(v2): Add theme

* feat(v2): improve sidebar definitions

* feat(v2): fix conflicts
This commit is contained in:
Fanny 2020-05-18 00:06:48 -03:00 committed by GitHub
parent 463efec20d
commit 7e97d40075
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 253 additions and 23 deletions

View file

@ -14,6 +14,12 @@ module.exports = {
src: 'img/logo.svg',
},
links: [
{
to: 'docs/doc1',
activeBasePath: 'docs',
label: 'Docs',
position: 'left',
},
{to: 'blog', label: 'Blog', position: 'left'},
{
href: 'https://github.com/facebook/docusaurus',

View file

@ -9,6 +9,7 @@
},
"dependencies": {
"bootstrap": "^4.4.1",
"classnames": "^2.2.6",
"prism-react-renderer": "^1.1.0",
"reactstrap": "^8.4.1",
"@mdx-js/react": "^1.5.8"

View file

@ -46,7 +46,7 @@ function DocItem(props) {
)}
{permalink && <meta property="og:url" content={siteUrl + permalink} />}
</Head>
<main className="col col-8 p-0">
<main className="col col-md-8 p-0">
<DocContent />
<DocPaginator metadata={metadata} />
</main>

View file

@ -7,22 +7,34 @@
import React from 'react';
import renderRoutes from '@docusaurus/renderRoutes';
import DocSidebar from '@theme/DocSidebar';
import MDXComponents from '@theme/MDXComponents';
import Layout from '@theme/Layout';
import {MDXProvider} from '@mdx-js/react';
import {matchPath} from '@docusaurus/router';
function DocPage(props) {
const {route: baseRoute} = props;
const {route: baseRoute, docsMetadata, location} = props;
// case-sensitive route such as it is defined in the sidebar
const currentRoute =
baseRoute.routes.find((route) => {
return matchPath(location.pathname, route);
}) || {};
const {permalinkToSidebar, docsSidebars} = docsMetadata;
const sidebar = permalinkToSidebar[currentRoute.path];
return (
<Layout title="Blog page" description="My blog page">
<div className="container mt-4">
<section className="row justify-content-center">
<Layout title="Doc page" description="My Doc page">
<DocSidebar
docsSidebars={docsSidebars}
path={currentRoute.path}
sidebar={sidebar}
/>
<section className="offset-1 mr-4 mt-4 col-xl-6 offset-xl-4 p-0 justify-content-center align-self-center overflow-hidden">
<MDXProvider components={MDXComponents}>
{renderRoutes(baseRoute.routes)}
</MDXProvider>
</section>
</div>
</Layout>
);
}

View file

@ -0,0 +1,135 @@
/**
* 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, {useState, useCallback} from 'react';
import Link from '@docusaurus/Link';
import isInternalUrl from '@docusaurus/isInternalUrl';
import {NavItem, Nav, Button} from 'reactstrap';
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
import classNames from 'classnames';
import styles from './styles.module.css';
const DocSidebarItem = ({item, onItemClick, ...props}) => {
const {items, href, label, type} = item;
switch (type) {
case 'category':
return (
items.length > 0 && (
<div>
<h4 className="ml-2">{label}</h4>
{items.map((childItem) => (
<DocSidebarItem
key={childItem.label}
item={childItem}
onItemClick={onItemClick}
/>
))}
</div>
)
);
case 'link':
default:
return (
<NavItem>
<Link
key={label}
className="sidebar-item m-4 text-white"
to={href}
{...(isInternalUrl(href)
? {
isNavLink: true,
activeClassName: 'active',
exact: true,
onClick: onItemClick,
}
: {
target: '_blank',
rel: 'noreferrer noopener',
})}
{...props}>
{label}
</Link>
</NavItem>
);
}
};
const DocSidebar = (props) => {
const {docsSidebars, sidebar: currentSidebar} = props;
const [sidebarShown, setSidebarShown] = useState(false);
const handleSidebarToggle = useCallback(() => {
setSidebarShown(!sidebarShown);
}, [sidebarShown, setSidebarShown]);
useLockBodyScroll(sidebarShown);
if (!currentSidebar) {
return null;
}
const sidebarData = docsSidebars[currentSidebar];
if (!sidebarData) {
throw new Error(
`Cannot find the sidebar "${currentSidebar}" in the sidebar config!`,
);
}
return (
<div className={classNames('bg-info', styles.sidebar)}>
<div
className={classNames('text-white', {
[styles.isOpen]: sidebarShown,
})}>
<div className="d-flex w-100 justify-content-end mr-5">
<Button
color="secondary"
onClick={handleSidebarToggle}
className={classNames('mr-2', styles.sidebarFAB)}>
<svg
aria-label="Menu"
xmlns="http://www.w3.org/2000/svg"
height={24}
width={24}
viewBox="0 0 32 32"
role="img"
focusable="false">
<title>Menu</title>
<path
stroke="currentColor"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M4 7h22M4 15h22M4 23h22"
/>
</svg>
</Button>
</div>
<div className={classNames(styles.sideMenu)}>
<Nav vertical className="list-unstyled p-3 mr-auto">
{sidebarData.map((item) => (
<DocSidebarItem
key={item.label}
item={item}
onItemClick={(e) => {
e.target.blur();
setSidebarShown(false);
}}
/>
))}
</Nav>
</div>
</div>
</div>
);
};
export default DocSidebar;

View file

@ -0,0 +1,58 @@
@media only screen and (min-width: 997px) {
.sidebar {
min-width: 300px;
max-width: 300px;
transition: all 0.5s;
min-height: 100vh;
margin-left: 0;
font-size: 16px;
}
.isOpen {
margin-left: 0;
transition: .5s;
}
.sidebar ul p {
color: #fff;
padding: 10px;
}
.sidebarFAB {
display: none;
}
}
@media only screen and (max-width: 500px) {
.isOpen .sideMenu{
min-width: 100%;
max-width: 100%;
width: 100%;
height: 100%;
position: absolute;
z-index: 1;
top: 0;
display: inherit;
background-color: #17a2b8;
align-items: stretch;
overflow: hidden;
transition: all 0.5s, height 0s;
}
.sideMenu {
display: none;
}
.sidebar {
width: 0;
}
.sidebarFAB {
display: inline-flex;
position: fixed;
z-index: 2;
right: 1rem;
bottom: 2rem;
}
}

View file

@ -39,7 +39,7 @@ function Footer() {
const {links} = footer || {};
return (
<footer className="container-fluid p-0 mt-3 align-self-end">
<footer className="container-fluid p-0 align-self-end">
<div className="row bg-light no-gutters justify-content-center">
{links && links.length > 0 && (
<>

View file

@ -40,7 +40,6 @@ function Layout(props) {
if (!isInternalUrl(metaImage)) {
metaImageUrl = metaImage;
}
const faviconUrl = useBaseUrl(favicon);
return (
@ -69,7 +68,9 @@ function Layout(props) {
<meta name="twitter:card" content="summary_large_image" />
</Head>
<Navbar />
<div className="vw-100 align-self-center">{children}</div>
<div className="container-fluid px-0 d-inline-flex flex-row">
{children}
</div>
{!noFooter && <Footer />}
</div>
);

View file

@ -49,10 +49,11 @@ function Navbar() {
isClient,
} = useDocusaurusContext();
const [sidebarShown, setSidebarShown] = useState(false);
const handleToggle = useCallback(() => {
setSidebarShown(!sidebarShown);
}, [sidebarShown, setSidebarShown]);
const [navbarShown, setNavbarShown] = useState(false);
const handleNavbarToggle = useCallback(() => {
setNavbarShown(!navbarShown);
}, [navbarShown, setNavbarShown]);
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
return (
@ -76,12 +77,8 @@ function Navbar() {
)}
{title != null && <span className="ml-2">{title}</span>}
</Link>
<NavbarToggler onClick={handleToggle} />
<Collapse
isOpen={sidebarShown}
navbar
className="justify-content-between">
<NavbarToggler onClick={handleNavbarToggle} />
<Collapse isOpen={navbarShown} navbar className="justify-content-between">
<Nav navbar>
{links != null &&
links.length !== 0 &&

View file

@ -0,0 +1,20 @@
/**
* 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 {useEffect} from 'react';
function useLockBodyScroll(lock = true) {
useEffect(() => {
document.body.style.overflow = lock ? 'hidden' : 'visible';
window.scrollTo(0, 0);
return () => {
document.body.style.overflow = 'visible';
};
}, [lock]);
}
export default useLockBodyScroll;