docs: added show/hide sidebar button (#4150)

* docs: added show/hide sidebar button

* added check for browser

* fix build error

* solve build errors
This commit is contained in:
Shahed Nasser
2023-05-22 19:44:50 +03:00
committed by GitHub
parent 0476f52519
commit 87444488b5
29 changed files with 589 additions and 188 deletions
@@ -1,24 +1,27 @@
import React from "react"
import React, { useContext } from "react"
import clsx from "clsx"
import { useDocsSidebar } from "@docusaurus/theme-common/internal"
import type { Props } from "@theme/DocPage/Layout/Main"
import { SidebarContext } from "@site/src/context/sidebar"
export default function DocPageLayoutMain({
hiddenSidebarContainer,
children,
}: Props): JSX.Element {
export default function DocPageLayoutMain({ children }: Props): JSX.Element {
const sidebar = useDocsSidebar()
const sidebarContext = useContext(SidebarContext)
return (
<main
className={clsx(
"tw-flex tw-flex-col tw-w-full lg:tw-flex-grow lg:tw-max-w-[calc(100%-320px)]",
(hiddenSidebarContainer || !sidebar) && "lg:tw-max-w-[calc(100%-30px)]"
"tw-flex tw-flex-col tw-w-full lg:tw-flex-grow",
(sidebarContext?.hiddenSidebarContainer || !sidebar) &&
"lg:tw-max-w-[calc(100%-30px)]",
!sidebarContext?.hiddenSidebarContainer &&
"xxl:tw-max-w-[1119px] lg:tw-max-w-[calc(100%-321px)]"
)}
>
<div
className={clsx(
"container padding-top--md tw-px-0",
hiddenSidebarContainer && "lg:tw-max-w-main-content-hidden-sidebar"
sidebarContext?.hiddenSidebarContainer &&
"lg:tw-max-w-main-content-hidden-sidebar"
)}
>
{children}
@@ -1,12 +1,12 @@
import React, { type ReactNode, useState, useCallback, useRef } from "react"
import React, { type ReactNode, useRef, useContext } from "react"
import clsx from "clsx"
import { ThemeClassNames } from "@docusaurus/theme-common"
import { useDocsSidebar } from "@docusaurus/theme-common/internal"
import { useLocation } from "@docusaurus/router"
import DocSidebar from "@theme/DocSidebar"
import ExpandButton from "@theme/DocPage/Layout/Sidebar/ExpandButton"
import type { Props } from "@theme/DocPage/Layout/Sidebar"
import { SwitchTransition, CSSTransition } from "react-transition-group"
import { SidebarContext } from "@site/src/context/sidebar"
// Reset sidebar state when sidebar changes
// Use React key to unmount/remount the children
@@ -23,18 +23,9 @@ function ResetOnSidebarChange({ children }: { children: ReactNode }) {
export default function DocPageLayoutSidebar({
sidebar,
hiddenSidebarContainer,
setHiddenSidebarContainer,
}: Props): JSX.Element {
const { pathname } = useLocation()
const [hiddenSidebar, setHiddenSidebar] = useState(false)
const toggleSidebar = useCallback(() => {
if (hiddenSidebar) {
setHiddenSidebar(false)
}
setHiddenSidebarContainer((value) => !value)
}, [setHiddenSidebarContainer, hiddenSidebar])
const sidebarContext = useContext(SidebarContext)
const { name } = useDocsSidebar()
const sidebarRef = useRef(null)
@@ -42,8 +33,13 @@ export default function DocPageLayoutSidebar({
<aside
className={clsx(
ThemeClassNames.docs.docSidebarContainer,
"lg:tw-block lg:tw-w-sidebar lg:tw-will-change-[width] lg:tw-transition-[width] lg:tw-ease-ease tw-clip tw-hidden tw-duration-200",
hiddenSidebarContainer && "lg:tw-w-sidebar-hidden lg:tw-cursor-pointer"
"lg:tw-block lg:tw-w-sidebar lg:tw-transition-[left] lg:tw-ease-ease lg:tw-duration-200 lg:tw-left-0 tw-hidden",
!hiddenSidebarContainer && "clip",
hiddenSidebarContainer &&
"lg:tw-fixed lg:tw-left-[-100%] lg:tw-rounded lg:tw-border-0 lg:tw-border-medusa-border-strong lg:dark:tw-border-medusa-border-strong-dark",
hiddenSidebarContainer &&
sidebarContext?.floatingSidebar &&
"lg:!tw-left-0.5 lg:tw-top-[65px] lg:tw-z-20 lg:tw-bg-docs-bg lg:dark:tw-bg-docs-bg-dark lg:tw-shadow-flyout lg:dark:tw-shadow-flyout-dark"
)}
onTransitionEnd={(e) => {
if (
@@ -55,7 +51,24 @@ export default function DocPageLayoutSidebar({
}
if (hiddenSidebarContainer) {
setHiddenSidebar(true)
sidebarContext?.setHiddenSidebar(true)
}
}}
onMouseLeave={() => {
setTimeout(() => {
if (!document.querySelector(".sidebar-toggler:hover")) {
sidebarContext?.setFloatingSidebar(false)
}
}, 100)
}}
onMouseUp={(e) => {
const target = e.target as Element
console.log("here", target.classList)
if (
target.classList.contains("menu__list-item") ||
target.parentElement.classList.contains("menu__list-item")
) {
sidebarContext?.setFloatingSidebar(false)
}
}}
>
@@ -80,12 +93,9 @@ export default function DocPageLayoutSidebar({
<DocSidebar
sidebar={sidebar}
path={pathname}
onCollapse={toggleSidebar}
isHidden={hiddenSidebar}
onCollapse={sidebarContext?.onCollapse}
isHidden={sidebarContext?.hiddenSidebar}
/>
{hiddenSidebar && (
<ExpandButton toggleSidebar={toggleSidebar} />
)}
</div>
</ResetOnSidebarChange>
</div>
@@ -0,0 +1,35 @@
import React, { useContext } from "react"
import { useDocsSidebar } from "@docusaurus/theme-common/internal"
import Layout from "@theme/Layout"
import BackToTopButton from "@theme/BackToTopButton"
import DocPageLayoutSidebar from "@theme/DocPage/Layout/Sidebar"
import DocPageLayoutMain from "@theme/DocPage/Layout/Main"
import type { Props } from "@theme/DocPage/Layout"
import { SidebarContext } from "@site/src/context/sidebar"
import clsx from "clsx"
export default function DocPageLayout({ children }: Props): JSX.Element {
const sidebar = useDocsSidebar()
const sidebarContext = useContext(SidebarContext)
return (
<Layout wrapperClassName={clsx("tw-flex tw-flex-[1_0_auto]")}>
<BackToTopButton />
<div className={clsx("tw-flex tw-w-full tw-flex-[1_0]")}>
{sidebar && (
<DocPageLayoutSidebar
sidebar={sidebar.items}
hiddenSidebarContainer={sidebarContext?.hiddenSidebarContainer}
setHiddenSidebarContainer={
sidebarContext?.setHiddenSidebarContainer
}
/>
)}
<DocPageLayoutMain
hiddenSidebarContainer={sidebarContext?.hiddenSidebarContainer}
>
{children}
</DocPageLayoutMain>
</div>
</Layout>
)
}
+62 -2
View File
@@ -1,9 +1,10 @@
import React from "react"
import React, { useCallback, useEffect, useState } from "react"
import clsx from "clsx"
import {
HtmlClassNameProvider,
ThemeClassNames,
PageMetadata,
prefersReducedMotion,
} from "@docusaurus/theme-common"
import {
docVersionSearchTag,
@@ -15,6 +16,7 @@ import DocPageLayout from "@theme/DocPage/Layout"
import NotFound from "@theme/NotFound"
import SearchMetadata from "@theme/SearchMetadata"
import type { Props } from "@theme/DocPage"
import { SidebarContext } from "@site/src/context/sidebar"
function DocPageMetadata(props: Props): JSX.Element {
const { versionMetadata } = props
@@ -43,6 +45,52 @@ export default function DocPage(props: Props): JSX.Element {
return <NotFound />
}
const { docElement, sidebarName, sidebarItems } = currentDocRouteMetadata
const [hiddenSidebar, setHiddenSidebar] = useState(false)
const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false)
const [floatingSidebar, setFloatingSidebar] = useState(false)
const toggleSidebar = useCallback(() => {
if (hiddenSidebar) {
setHiddenSidebar(false)
}
// onTransitionEnd won't fire when sidebar animation is disabled
// fixes https://github.com/facebook/docusaurus/issues/8918
if (!hiddenSidebar && prefersReducedMotion()) {
setHiddenSidebar(true)
}
setHiddenSidebarContainer((value) => !value)
}, [setHiddenSidebarContainer, hiddenSidebar])
useEffect(() => {
function isEditingContent(event: KeyboardEvent) {
const element = event.target as HTMLElement
const tagName = element.tagName
return (
element.isContentEditable ||
tagName === "INPUT" ||
tagName === "SELECT" ||
tagName === "TEXTAREA"
)
}
function sidebarShortcut(e: KeyboardEvent) {
if (
(e.metaKey || e.ctrlKey) &&
e.key.toLowerCase() === "i" &&
!isEditingContent(e)
) {
e.preventDefault()
toggleSidebar()
}
}
window.addEventListener("keydown", sidebarShortcut)
return () => {
window.removeEventListener("keydown", sidebarShortcut)
}
})
return (
<>
<DocPageMetadata {...props} />
@@ -57,7 +105,19 @@ export default function DocPage(props: Props): JSX.Element {
>
<DocsVersionProvider version={versionMetadata}>
<DocsSidebarProvider name={sidebarName} items={sidebarItems}>
<DocPageLayout>{docElement}</DocPageLayout>
<SidebarContext.Provider
value={{
hiddenSidebar,
setHiddenSidebar,
hiddenSidebarContainer,
setHiddenSidebarContainer,
floatingSidebar,
setFloatingSidebar,
onCollapse: toggleSidebar,
}}
>
<DocPageLayout>{docElement}</DocPageLayout>
</SidebarContext.Provider>
</DocsSidebarProvider>
</DocsVersionProvider>
</HtmlClassNameProvider>