From fa06aceaee0200185c4088e47484c1cf503a8279 Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Tue, 23 Feb 2021 14:47:06 +0300 Subject: [PATCH] feat(v2): mobile TOC --- .../__snapshots__/index.test.ts.snap | 268 ++++++++++++++++-- .../src/__tests__/index.test.ts | 6 +- .../src/globalData.ts | 1 + .../src/index.ts | 29 +- .../src/plugin-content-docs.d.ts | 8 +- .../src/props.ts | 2 +- .../src/theme/hooks/useDocs.ts | 16 ++ .../src/types.ts | 3 +- .../src/theme/DocPage/index.tsx | 13 +- .../src/theme/DocItem/index.tsx | 60 +++- .../src/theme/DocItem/styles.module.css | 77 +++++ .../src/theme/DocPage/index.tsx | 10 +- .../src/theme/DocSidebar/index.tsx | 10 +- .../theme/NavbarItem/DefaultNavbarItem.tsx | 58 +++- .../src/theme/NavbarItem/DocNavbarItem.tsx | 1 + .../src/theme/TOC/index.tsx | 11 +- .../docusaurus-theme-classic/src/types.d.ts | 17 ++ .../src/validateThemeConfig.js | 2 + .../src/utils/useThemeConfig.ts | 1 + website/docusaurus.config.js | 1 + 20 files changed, 507 insertions(+), 87 deletions(-) diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap index fe937af19184..f166c21291bf 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/__snapshots__/index.test.ts.snap @@ -128,6 +128,60 @@ Object { "mainDocId": "hello", "name": "current", "path": "/docs", + "sidebars": Object { + "docs": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/foo/bar", + "label": "Bar", + "type": "link", + }, + Object { + "customProps": undefined, + "href": "/docs/foo/bazSlug.html", + "label": "baz", + "type": "link", + }, + ], + "label": "foo", + "type": "category", + }, + Object { + "href": "https://github.com", + "label": "Github", + "type": "link", + }, + Object { + "customProps": undefined, + "href": "/docs/", + "label": "Hello, World !", + "type": "link", + }, + ], + "label": "Test", + "type": "category", + }, + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/", + "label": "Hello, World !", + "type": "link", + }, + ], + "label": "Guides", + "type": "category", + }, + ], + }, }, ], }, @@ -355,11 +409,6 @@ Object { ] } ] - }, - \\"permalinkToSidebar\\": { - \\"/docs/foo/bar\\": \\"docs\\", - \\"/docs/foo/bazSlug.html\\": \\"docs\\", - \\"/docs/\\": \\"docs\\" } }", } @@ -444,6 +493,60 @@ Object { "mainDocId": "hello", "name": "current", "path": "/docs", + "sidebars": Object { + "docs": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/foo/bar", + "label": "Bar", + "type": "link", + }, + Object { + "customProps": undefined, + "href": "/docs/foo/bazSlug.html", + "label": "baz", + "type": "link", + }, + ], + "label": "foo", + "type": "category", + }, + Object { + "href": "https://github.com", + "label": "Github", + "type": "link", + }, + Object { + "customProps": undefined, + "href": "/docs/", + "label": "Hello, World !", + "type": "link", + }, + ], + "label": "Test", + "type": "category", + }, + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/", + "label": "Hello, World !", + "type": "link", + }, + ], + "label": "Guides", + "type": "category", + }, + ], + }, }, ], }, @@ -653,9 +756,6 @@ Object { \\"href\\": \\"/community/team\\" } ] - }, - \\"permalinkToSidebar\\": { - \\"/community/team\\": \\"version-1.0.0/community\\" } }", "version-current-metadata-prop-751.json": "{ @@ -671,9 +771,6 @@ Object { \\"href\\": \\"/community/next/team\\" } ] - }, - \\"permalinkToSidebar\\": { - \\"/community/next/team\\": \\"community\\" } }", } @@ -698,6 +795,16 @@ Object { "mainDocId": "team", "name": "current", "path": "/community/next", + "sidebars": Object { + "community": Array [ + Object { + "customProps": undefined, + "href": "/community/next/team", + "label": "Team title translated", + "type": "link", + }, + ], + }, }, Object { "docs": Array [ @@ -712,6 +819,16 @@ Object { "mainDocId": "team", "name": "1.0.0", "path": "/community", + "sidebars": Object { + "version-1.0.0/community": Array [ + Object { + "customProps": undefined, + "href": "/community/team", + "label": "team", + "type": "link", + }, + ], + }, }, ], }, @@ -1141,11 +1258,6 @@ Object { ] } ] - }, - \\"permalinkToSidebar\\": { - \\"/docs/1.0.0/foo/barSlug\\": \\"version-1.0.0/docs\\", - \\"/docs/1.0.0/foo/baz\\": \\"version-1.0.0/docs\\", - \\"/docs/1.0.0/\\": \\"version-1.0.0/docs\\" } }", "version-1-0-1-metadata-prop-e87.json": "{ @@ -1180,10 +1292,6 @@ Object { ] } ] - }, - \\"permalinkToSidebar\\": { - \\"/docs/foo/bar\\": \\"version-1.0.1/docs\\", - \\"/docs/\\": \\"version-1.0.1/docs\\" } }", "version-current-metadata-prop-751.json": "{ @@ -1218,10 +1326,6 @@ Object { ] } ] - }, - \\"permalinkToSidebar\\": { - \\"/docs/next/foo/barSlug\\": \\"docs\\", - \\"/docs/next/\\": \\"docs\\" } }", "version-with-slugs-metadata-prop-2bf.json": "{ @@ -1244,9 +1348,6 @@ Object { ] } ] - }, - \\"permalinkToSidebar\\": { - \\"/docs/withSlugs/rootAbsoluteSlug\\": \\"version-1.0.1/docs\\" } }", } @@ -1296,6 +1397,36 @@ Object { "mainDocId": "hello", "name": "current", "path": "/docs/next", + "sidebars": Object { + "docs": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/next/foo/barSlug", + "label": "bar", + "type": "link", + }, + ], + "label": "Test", + "type": "category", + }, + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/next/", + "label": "hello", + "type": "link", + }, + ], + "label": "Guides", + "type": "category", + }, + ], + }, }, Object { "docs": Array [ @@ -1315,6 +1446,36 @@ Object { "mainDocId": "hello", "name": "1.0.1", "path": "/docs", + "sidebars": Object { + "version-1.0.1/docs": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/foo/bar", + "label": "bar", + "type": "link", + }, + ], + "label": "Test", + "type": "category", + }, + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/", + "label": "hello", + "type": "link", + }, + ], + "label": "Guides", + "type": "category", + }, + ], + }, }, Object { "docs": Array [ @@ -1339,6 +1500,42 @@ Object { "mainDocId": "hello", "name": "1.0.0", "path": "/docs/1.0.0", + "sidebars": Object { + "version-1.0.0/docs": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/1.0.0/foo/barSlug", + "label": "bar", + "type": "link", + }, + Object { + "customProps": undefined, + "href": "/docs/1.0.0/foo/baz", + "label": "baz", + "type": "link", + }, + ], + "label": "Test", + "type": "category", + }, + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/1.0.0/", + "label": "hello", + "type": "link", + }, + ], + "label": "Guides", + "type": "category", + }, + ], + }, }, Object { "docs": Array [ @@ -1388,6 +1585,23 @@ Object { "mainDocId": "rootAbsoluteSlug", "name": "withSlugs", "path": "/docs/withSlugs", + "sidebars": Object { + "version-1.0.1/docs": Array [ + Object { + "collapsed": true, + "items": Array [ + Object { + "customProps": undefined, + "href": "/docs/withSlugs/rootAbsoluteSlug", + "label": "rootAbsoluteSlug", + "type": "link", + }, + ], + "label": "Test", + "type": "category", + }, + ], + }, }, ], }, diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts index 753b977c7d05..01712daac6a7 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/index.test.ts @@ -83,9 +83,9 @@ Entries created: `version-${kebabCase(version.versionName)}-metadata-prop`, ); expect(versionMetadataProp.docsSidebars).toEqual(toSidebarsProp(version)); - expect(versionMetadataProp.permalinkToSidebar).toEqual( - version.permalinkToSidebar, - ); + // expect(versionMetadataProp.permalinkToSidebar).toEqual( + // version.permalinkToSidebar, + // ); }, expectSnapshot: () => { diff --git a/packages/docusaurus-plugin-content-docs/src/globalData.ts b/packages/docusaurus-plugin-content-docs/src/globalData.ts index 64ca58bd1115..41cb8dea46f8 100644 --- a/packages/docusaurus-plugin-content-docs/src/globalData.ts +++ b/packages/docusaurus-plugin-content-docs/src/globalData.ts @@ -23,5 +23,6 @@ export function toGlobalDataVersion(version: LoadedVersion): GlobalVersion { path: version.versionPath, mainDocId: version.mainDocId, docs: version.docs.map(toGlobalDataDoc), + sidebars: version.sidebars, }; } diff --git a/packages/docusaurus-plugin-content-docs/src/index.ts b/packages/docusaurus-plugin-content-docs/src/index.ts index 05e64ba0d99c..086493b52d25 100644 --- a/packages/docusaurus-plugin-content-docs/src/index.ts +++ b/packages/docusaurus-plugin-content-docs/src/index.ts @@ -37,8 +37,9 @@ import { LoadedVersion, DocFile, DocsMarkdownOption, + Sidebars, } from './types'; -import {PermalinkToSidebar} from '@docusaurus/plugin-content-docs-types'; +// import {PermalinkToSidebar} from '@docusaurus/plugin-content-docs-types'; import {RuleSetRule} from 'webpack'; import {cliDocsVersionCommand} from './cli'; import {VERSIONS_JSON_FILE} from './constants'; @@ -208,12 +209,12 @@ export default function pluginContentDocs( }); // TODO really useful? replace with global state logic? - const permalinkToSidebar: PermalinkToSidebar = {}; - Object.values(docs).forEach((doc) => { - if (doc.sidebar) { - permalinkToSidebar[doc.permalink] = doc.sidebar; - } - }); + // const permalinkToSidebar: PermalinkToSidebar = {}; + // Object.values(docs).forEach((doc) => { + // if (doc.sidebar) { + // permalinkToSidebar[doc.permalink] = doc.sidebar; + // } + // }); // The "main doc" is the "version entry point" // We browse this doc by clicking on a version: @@ -239,7 +240,7 @@ export default function pluginContentDocs( ...versionMetadata, mainDocId: getMainDoc().unversionedId, sidebars, - permalinkToSidebar, + // permalinkToSidebar, docs: docs.map(addNavData), }; } @@ -285,15 +286,12 @@ export default function pluginContentDocs( }; async function handleVersion(loadedVersion: LoadedVersion) { + const versionMetadata = toVersionMetadataProp(pluginId, loadedVersion); const versionMetadataPropPath = await createData( `${docuHash( `version-${loadedVersion.versionName}-metadata-prop`, )}.json`, - JSON.stringify( - toVersionMetadataProp(pluginId, loadedVersion), - null, - 2, - ), + JSON.stringify(versionMetadata, null, 2), ); addRoute({ @@ -309,6 +307,11 @@ export default function pluginContentDocs( }, priority: loadedVersion.routePriority, }); + + // + loadedVersion.sidebars = versionMetadata.docsSidebars as Sidebars; + + return loadedVersion; } await Promise.all(loadedVersions.map(handleVersion)); diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index 258b9b22c285..de81526a3cdd 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -8,9 +8,9 @@ /* eslint-disable camelcase */ declare module '@docusaurus/plugin-content-docs-types' { - export type PermalinkToSidebar = { - [permalink: string]: string; - }; + // export type PermalinkToSidebar = { + // [permalink: string]: string; + // }; export type PropVersionMetadata = { pluginId: string; @@ -18,7 +18,7 @@ declare module '@docusaurus/plugin-content-docs-types' { label: string; isLast: boolean; docsSidebars: PropSidebars; - permalinkToSidebar: PermalinkToSidebar; + // permalinkToSidebar: PermalinkToSidebar; }; type PropsSidebarItemBase = { diff --git a/packages/docusaurus-plugin-content-docs/src/props.ts b/packages/docusaurus-plugin-content-docs/src/props.ts index b0c512c191ce..6fc67e26a0ba 100644 --- a/packages/docusaurus-plugin-content-docs/src/props.ts +++ b/packages/docusaurus-plugin-content-docs/src/props.ts @@ -72,6 +72,6 @@ export function toVersionMetadataProp( label: loadedVersion.versionLabel, isLast: loadedVersion.isLast, docsSidebars: toSidebarsProp(loadedVersion), - permalinkToSidebar: loadedVersion.permalinkToSidebar, + // permalinkToSidebar: loadedVersion.permalinkToSidebar, }; } diff --git a/packages/docusaurus-plugin-content-docs/src/theme/hooks/useDocs.ts b/packages/docusaurus-plugin-content-docs/src/theme/hooks/useDocs.ts index 6e14f3106c84..4dce9a58915f 100644 --- a/packages/docusaurus-plugin-content-docs/src/theme/hooks/useDocs.ts +++ b/packages/docusaurus-plugin-content-docs/src/theme/hooks/useDocs.ts @@ -82,3 +82,19 @@ export const useDocVersionSuggestions = (pluginId: string | undefined) => { const {pathname} = useLocation(); return getDocVersionSuggestions(data, pathname); }; + +export const useActiveDocSidebar = (pluginId: string | undefined) => { + const {activeVersion, activeDoc} = useActiveDocContext(pluginId); + + if (activeDoc && activeDoc.sidebar) { + return { + sidebarName: activeDoc.sidebar, + sidebar: activeVersion?.sidebars[activeDoc.sidebar], + }; + } + + return { + sidebarName: null, + sidebar: [], + }; +}; diff --git a/packages/docusaurus-plugin-content-docs/src/types.ts b/packages/docusaurus-plugin-content-docs/src/types.ts index be171ee7793f..04850675d63d 100644 --- a/packages/docusaurus-plugin-content-docs/src/types.ts +++ b/packages/docusaurus-plugin-content-docs/src/types.ts @@ -164,7 +164,7 @@ export type LoadedVersion = VersionMetadata & { mainDocId: string; docs: DocMetadata[]; sidebars: Sidebars; - permalinkToSidebar: Record; + // permalinkToSidebar: Record; }; export type LoadedContent = { @@ -184,6 +184,7 @@ export type GlobalVersion = { path: string; mainDocId: string; // home doc (if docs homepage configured), or first doc docs: GlobalDoc[]; + sidebars: Sidebars; }; export type GlobalPluginData = { diff --git a/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx b/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx index 54828fc32dfd..35735e882fba 100644 --- a/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx +++ b/packages/docusaurus-theme-bootstrap/src/theme/DocPage/index.tsx @@ -14,23 +14,20 @@ import Layout from '@theme/Layout'; import {MDXProvider} from '@mdx-js/react'; import {matchPath} from '@docusaurus/router'; import type {Props} from '@theme/DocPage'; -import type {DocumentRoute} from '@theme/DocItem'; import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types'; +import {useActiveDocSidebar} from '@theme/hooks/useDocs'; type DocPageContentProps = { - readonly currentDocRoute: DocumentRoute; readonly versionMetadata: PropVersionMetadata; readonly children: ReactNode; }; function DocPageContent({ - currentDocRoute, versionMetadata, children, }: DocPageContentProps): JSX.Element { - const {permalinkToSidebar, docsSidebars} = versionMetadata; - const sidebarName = permalinkToSidebar[currentDocRoute.path]; - const sidebar = docsSidebars[sidebarName]; + const {pluginId} = versionMetadata; + const {sidebarName, sidebar} = useActiveDocSidebar(pluginId); return (
@@ -60,9 +57,7 @@ function DocPage(props: Props): JSX.Element { return ; } return ( - + {renderRoutes(docRoutes)} ); diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx index 764eac5492ba..84f9a4f6bc23 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/index.tsx @@ -5,21 +5,24 @@ * LICENSE file in the root directory of this source tree. */ -import React from 'react'; +import React, {useState} from 'react'; +import clsx from 'clsx'; + +import { + useActivePlugin, + useVersions, + useActiveVersion, +} from '@theme/hooks/useDocs'; +import useLockBodyScroll from '@theme/hooks/useLockBodyScroll'; import DocPaginator from '@theme/DocPaginator'; import DocVersionSuggestions from '@theme/DocVersionSuggestions'; import Seo from '@theme/Seo'; import type {Props} from '@theme/DocItem'; -import TOC from '@theme/TOC'; +import TOC, {Headings} from '@theme/TOC'; import EditThisPage from '@theme/EditThisPage'; +import IconMenu from '@theme/IconMenu'; -import clsx from 'clsx'; import styles from './styles.module.css'; -import { - useActivePlugin, - useVersions, - useActiveVersion, -} from '@theme/hooks/useDocs'; function DocItem(props: Props): JSX.Element { const {content: DocContent} = props; @@ -43,6 +46,10 @@ function DocItem(props: Props): JSX.Element { // See https://github.com/facebook/docusaurus/issues/3362 const showVersionBadge = versions.length > 1; + const [showMobileToc, setShowMobileToc] = useState(false); + + useLockBodyScroll(showMobileToc); + return ( <> @@ -129,6 +136,43 @@ function DocItem(props: Props): JSX.Element {
)} + +
+ +
+
+ + +
+ +
+ + +
+
); } diff --git a/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css b/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css index 6c365bdf7455..b5c0e2440718 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css +++ b/packages/docusaurus-theme-classic/src/theme/DocItem/styles.module.css @@ -19,12 +19,89 @@ .docItemCol { max-width: 75% !important; } + + .mobileToc { + display: none; + } } @media only screen and (max-width: 996px) { .docItemContainer { padding: 0 0.3rem; } + + .mobileToc { + position: fixed; + left: 50%; + top: 50%; + z-index: calc(var(--ifm-z-index-fixed) + 2); + width: 100%; + height: 100%; + background-color: #fff; + box-shadow: var(--ifm-global-shadow-md); + transform: translate(-50%, -50%) translateX(100%); + max-height: 50vh; + transition: transform var(--ifm-transition-fast) ease; + } + + .mobileTocOpened { + transform: translate(-50%, -50%) translateX(0); + } + + .mobileTocContainer { + position: relative; + height: 100%; + } + + .mobileTocCloseButton { + position: absolute; + top: 0.5rem; + right: 0.5rem; + height: 2rem; + width: 2rem; + box-shadow: 4px 2px 4px rgba(0, 0, 0, 0.1); + border-radius: 100%; + color: var(--ifm-color-gray-900); + padding: 0; + font-size: 1.5rem; + font-weight: var(--ifm-font-weight-bold); + line-height: 0.9; + text-align: center; + } + + .mobileTocOpenButton { + position: fixed; + top: 0; + left: 0; + border: none; + border-radius: 100% 0 0 100%; + height: 2.5rem; + width: 2.5rem; + box-shadow: -3px 3px 4px rgba(0, 0, 0, 0.1); + transform: translateX(-100%); + } + + .mobileTocContent { + height: 100%; + overflow-y: auto; + } + + .mobileTocContent > ul { + font-weight: var(--ifm-font-weight-semibold); + font-size: 16px; + width: 90%; + } + + .mobileTocOverlay { + background-color: rgba(0, 0, 0, 0.6); + bottom: 0; + display: none; + left: 0; + right: 0; + position: fixed; + top: 0; + z-index: calc(var(--ifm-z-index-fixed) + 1); + } } .docLastUpdatedAt { diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx index df33dcf7a40d..91e16f3e9ff3 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/index.tsx @@ -9,6 +9,7 @@ import React, {ReactNode, useState, useCallback} from 'react'; import {MDXProvider} from '@mdx-js/react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import {useActiveDocSidebar} from '@theme/hooks/useDocs'; import renderRoutes from '@docusaurus/renderRoutes'; import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs-types'; import Layout from '@theme/Layout'; @@ -37,9 +38,8 @@ function DocPageContent({ children, }: DocPageContentProps): JSX.Element { const {siteConfig, isClient} = useDocusaurusContext(); - const {pluginId, permalinkToSidebar, docsSidebars, version} = versionMetadata; - const sidebarName = permalinkToSidebar[currentDocRoute.path]; - const sidebar = docsSidebars[sidebarName]; + const {pluginId, version} = versionMetadata; + const {sidebarName, sidebar} = useActiveDocSidebar(pluginId); const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false); const [hiddenSidebar, setHiddenSidebar] = useState(false); @@ -84,9 +84,7 @@ function DocPageContent({ } sidebar={sidebar} path={currentDocRoute.path} - sidebarCollapsible={ - siteConfig.themeConfig?.sidebarCollapsible ?? true - } + sidebarCollapsible={siteConfig.themeConfig.sidebarCollapsible} onCollapse={toggleSidebar} isHidden={hiddenSidebar} /> diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx index 19e3fa9848fa..39ade4c01646 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebar/index.tsx @@ -17,12 +17,12 @@ import isInternalUrl from '@docusaurus/isInternalUrl'; import type {Props} from '@theme/DocSidebar'; import Logo from '@theme/Logo'; import IconArrow from '@theme/IconArrow'; -import IconMenu from '@theme/IconMenu'; +// import IconMenu from '@theme/IconMenu'; import {translate} from '@docusaurus/Translate'; import styles from './styles.module.css'; -const MOBILE_TOGGLE_SIZE = 24; +// const MOBILE_TOGGLE_SIZE = 24; function usePrevious(value) { const ref = useRef(value); @@ -171,7 +171,7 @@ function DocSidebarItemLink({ ); } -function DocSidebarItem(props) { +export function DocSidebarItem(props) { switch (props.item.type) { case 'category': return ; @@ -224,7 +224,7 @@ function DocSidebar({ !isAnnouncementBarClosed && scrollY === 0, }, )}> - + */}
    {sidebar.map((item) => ( + {sidebar.map((item) => ( + + ))} + + ); +} function NavLink({ activeBasePath, @@ -62,6 +94,7 @@ function NavItemDesktop({ items, position, className, + docId: _docId, // Need to destructure position from props so that it doesn't get passed on. ...props }: DesktopOrMobileNavBarItemProps) { const dropdownRef = useRef(null); @@ -152,6 +185,7 @@ function NavItemMobile({ items, className, position: _position, // Need to destructure position from props so that it doesn't get passed on. + docId, ...props }: DesktopOrMobileNavBarItemProps) { const menuListRef = useRef(null); @@ -169,10 +203,32 @@ function NavItemMobile({ extraClassName, ); + const plugin = useActivePlugin({failfast: false}); + const pluginId = plugin ? plugin.pluginId : undefined; + let showDocSidebar = false; + + const {activeVersion, activeDoc} = useActiveDocContext(pluginId); + const {preferredVersion} = useDocsPreferredVersion(pluginId); + const latestVersion = useLatestVersion(pluginId); + const version = activeVersion ?? preferredVersion ?? latestVersion; + const doc = version.docs.find((versionDoc) => versionDoc.id === docId); + const isMainDoc = + version.mainDocId === docId && activeDoc?.sidebar === doc.sidebar; + const firstDocInActiveSidebar = activeVersion?.sidebars[doc?.sidebar]?.some( + (i) => i.href === pathname, + ); + showDocSidebar = isMainDoc || firstDocInActiveSidebar; + if (!items) { return (
  • + + {showDocSidebar && ( +
      + +
    + )}
  • ); } diff --git a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx index f5f60c665af7..b595ff4bace4 100644 --- a/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx +++ b/packages/docusaurus-theme-classic/src/theme/NavbarItem/DocNavbarItem.tsx @@ -45,6 +45,7 @@ Available docIds=\n- ${version.docs.join('\n- ')}`, })} label={staticLabel ?? doc.id} to={doc.path} + docId={docId} /> ); } diff --git a/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx b/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx index 831c26b10e9b..c81c0cb5d8b0 100644 --- a/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/TOC/index.tsx @@ -8,22 +8,15 @@ import React from 'react'; import clsx from 'clsx'; import useTOCHighlight from '@theme/hooks/useTOCHighlight'; -import type {TOCProps} from '@theme/TOC'; +import type {TOCProps, HeadingsProps} from '@theme/TOC'; import styles from './styles.module.css'; -import {TOCItem} from '@docusaurus/types'; const LINK_CLASS_NAME = 'table-of-contents__link'; const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active'; const TOP_OFFSET = 100; /* eslint-disable jsx-a11y/control-has-associated-label */ -function Headings({ - toc, - isChild, -}: { - toc: readonly TOCItem[]; - isChild?: boolean; -}) { +export function Headings({toc, isChild}: HeadingsProps) { if (!toc.length) { return null; } diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts index b4d5866db195..0e499ce9f60e 100644 --- a/packages/docusaurus-theme-classic/src/types.d.ts +++ b/packages/docusaurus-theme-classic/src/types.d.ts @@ -83,6 +83,15 @@ declare module '@theme/DocSidebar' { readonly isHidden: boolean; }; + export type DocSidebarItemProps = { + readonly item: PropSidebarItem; + readonly activePath: string; + readonly collapsible: boolean; + readonly onItemClick: () => void; + }; + + export const DocSidebarItem: (props: DocSidebarItemProps) => JSX.Element; + const DocSidebar: (props: Props) => JSX.Element; export default DocSidebar; } @@ -302,6 +311,7 @@ declare module '@theme/NavbarItem/DefaultNavbarItem' { readonly items?: readonly NavLinkProps[]; readonly position?: 'left' | 'right'; readonly className?: string; + readonly docId?: string; }; export type Props = DesktopOrMobileNavBarItemProps & { @@ -449,6 +459,13 @@ declare module '@theme/TOC' { readonly toc: readonly TOCItem[]; }; + export type HeadingsProps = { + readonly toc: readonly TOCItem[]; + readonly isChild?: boolean; + }; + + export const Headings: (props: HeadingsProps) => JSX.Element; + const TOC: (props: TOCProps) => JSX.Element; export default TOC; } diff --git a/packages/docusaurus-theme-classic/src/validateThemeConfig.js b/packages/docusaurus-theme-classic/src/validateThemeConfig.js index a89fc6022cf6..090e22e82837 100644 --- a/packages/docusaurus-theme-classic/src/validateThemeConfig.js +++ b/packages/docusaurus-theme-classic/src/validateThemeConfig.js @@ -41,6 +41,7 @@ const DEFAULT_CONFIG = { items: [], }, hideableSidebar: false, + sidebarCollapsible: true, }; exports.DEFAULT_CONFIG = DEFAULT_CONFIG; @@ -310,6 +311,7 @@ const ThemeConfigSchema = Joi.object({ .default(DEFAULT_CONFIG.prism) .unknown(), hideableSidebar: Joi.bool().default(DEFAULT_CONFIG.hideableSidebar), + sidebarCollapsible: Joi.bool().default(DEFAULT_CONFIG.sidebarCollapsible), }); exports.ThemeConfigSchema = ThemeConfigSchema; diff --git a/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts b/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts index 84e2895b44be..1d77bfa3471c 100644 --- a/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts +++ b/packages/docusaurus-theme-common/src/utils/useThemeConfig.ts @@ -70,6 +70,7 @@ export type ThemeConfig = { prism: any; footer: Footer | undefined; hideableSidebar: any; + sidebarCollapsible: any; }; export function useThemeConfig(): ThemeConfig { diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index f83ea28561f8..b54a14756a87 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -330,6 +330,7 @@ const LocaleConfigs = isI18nStaging {to: 'blog', label: 'Blog', position: 'left'}, {to: 'showcase', label: 'Showcase', position: 'left'}, { + docId: 'support', to: '/community/support', label: 'Community', position: 'left',