diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 04bda1f92521..c20cf7392990 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -268,7 +268,7 @@ declare module '@theme/DocPage/Layout' { export default function DocPageLayout(props: Props): JSX.Element; } -declare module '@theme/DocPage/Layout/Aside' { +declare module '@theme/DocPage/Layout/Sidebar' { import type {Dispatch, SetStateAction} from 'react'; import type {PropSidebar} from '@docusaurus/plugin-content-docs'; @@ -278,7 +278,17 @@ declare module '@theme/DocPage/Layout/Aside' { readonly setHiddenSidebarContainer: Dispatch>; } - export default function DocPageLayoutAside(props: Props): JSX.Element; + export default function DocPageLayoutSidebar(props: Props): JSX.Element; +} + +declare module '@theme/DocPage/Layout/Sidebar/ExpandButton' { + export interface Props { + toggleSidebar: () => void; + } + + export default function DocPageLayoutSidebarExpandButton( + props: Props, + ): JSX.Element; } declare module '@theme/DocPage/Layout/Main' { diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.module.css b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.module.css new file mode 100644 index 000000000000..0754fce24b02 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.module.css @@ -0,0 +1,28 @@ +/** + * 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. + */ + +.docMainContainer { + display: flex; + width: 100%; +} + +@media (min-width: 997px) { + .docMainContainer { + flex-grow: 1; + max-width: calc(100% - var(--doc-sidebar-width)); + } + + .docMainContainerEnhanced { + max-width: calc(100% - var(--doc-sidebar-hidden-width)); + } + + .docItemWrapperEnhanced { + max-width: calc( + var(--ifm-container-width) + var(--doc-sidebar-width) + ) !important; + } +} diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx index 3cc4f0479e00..7ae012469544 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx @@ -10,7 +10,7 @@ import React from 'react'; import {useDocsSidebar} from '@docusaurus/theme-common'; import clsx from 'clsx'; -import styles from './styles.module.css'; +import styles from './Main.module.css'; import type {Props} from '@theme/DocPage/Layout/Main'; export default function DocPageLayoutMain({ diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.module.css b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.module.css new file mode 100644 index 000000000000..8df23b581d4c --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.module.css @@ -0,0 +1,37 @@ +/** + * 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. + */ + +@media (min-width: 997px) { + .expandButton { + position: sticky; + top: 0; + height: 100%; + max-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + transition: background-color var(--ifm-transition-fast) ease; + } + + .expandButton:hover, + .expandButton:focus { + background-color: var(--ifm-color-emphasis-200); + } + + .expandButtonIcon { + transform: rotate(0); + } + + [dir='rtl'] .expandButtonIcon { + transform: rotate(180deg); + } + + [data-theme='dark'] .expandButton:hover, + [data-theme='dark'] .expandButton:focus { + background-color: var(--collapse-button-bg-color-dark); + } +} diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.tsx new file mode 100644 index 000000000000..69dcd5937e5f --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.tsx @@ -0,0 +1,40 @@ +/** + * 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 IconArrow from '@theme/IconArrow'; +import {translate} from '@docusaurus/Translate'; +import type {Props} from '@theme/DocPage/Layout/Sidebar/ExpandButton'; + +import styles from './ExpandButton.module.css'; + +export default function DocPageLayoutSidebarExpandButton({ + toggleSidebar, +}: Props): JSX.Element { + return ( +
+ +
+ ); +} diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/index.module.css b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/index.module.css new file mode 100644 index 000000000000..52a371cc3fb2 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/index.module.css @@ -0,0 +1,32 @@ +/** + * 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. + */ + +:root { + --doc-sidebar-width: 300px; + --doc-sidebar-hidden-width: 30px; +} + +.docSidebarContainer { + display: none; +} + +@media (min-width: 997px) { + .docSidebarContainer { + display: block; + width: var(--doc-sidebar-width); + margin-top: calc(-1 * var(--ifm-navbar-height)); + border-right: 1px solid var(--ifm-toc-border-color); + will-change: width; + transition: width var(--ifm-transition-fast) ease; + clip-path: inset(0); + } + + .docSidebarContainerHidden { + width: var(--doc-sidebar-hidden-width); + cursor: pointer; + } +} diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Aside.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/index.tsx similarity index 63% rename from packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Aside.tsx rename to packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/index.tsx index 236382eae4ff..438d9f814e79 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Aside.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/index.tsx @@ -7,41 +7,15 @@ import React, {type ReactNode, useState, useCallback} from 'react'; import DocSidebar from '@theme/DocSidebar'; -import IconArrow from '@theme/IconArrow'; -import {translate} from '@docusaurus/Translate'; import {useLocation} from '@docusaurus/router'; -import type {Props} from '@theme/DocPage/Layout/Aside'; +import type {Props} from '@theme/DocPage/Layout/Sidebar'; +import ExpandButton from '@theme/DocPage/Layout/Sidebar/ExpandButton'; import clsx from 'clsx'; -import styles from './styles.module.css'; +import styles from './index.module.css'; import {ThemeClassNames, useDocsSidebar} from '@docusaurus/theme-common'; -function SidebarExpandButton({toggleSidebar}: {toggleSidebar: () => void}) { - return ( -
- -
- ); -} - // Reset sidebar state when sidebar changes // Use React key to unmount/remount the children // See https://github.com/facebook/docusaurus/issues/3414 @@ -54,7 +28,7 @@ function ResetOnSidebarChange({children}: {children: ReactNode}) { ); } -export default function DocPageLayoutAside({ +export default function DocPageLayoutSidebar({ sidebar, hiddenSidebarContainer, setHiddenSidebarContainer, @@ -94,7 +68,7 @@ export default function DocPageLayoutAside({ /> - {hiddenSidebar && } + {hiddenSidebar && } ); } diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.module.css b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.module.css new file mode 100644 index 000000000000..2516de55e3d4 --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.module.css @@ -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. + */ + +.docPage { + display: flex; + width: 100%; +} + +.docsWrapper { + display: flex; +} diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.tsx index 858a24e39183..8f95807481fd 100644 --- a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/index.tsx @@ -9,10 +9,10 @@ import React, {useState} from 'react'; import Layout from '@theme/Layout'; import BackToTopButton from '@theme/BackToTopButton'; import type {Props} from '@theme/DocPage/Layout'; -import DocPageLayoutAside from '@theme/DocPage/Layout/Aside'; +import DocPageLayoutSidebar from '@theme/DocPage/Layout/Sidebar'; import DocPageLayoutMain from '@theme/DocPage/Layout/Main'; -import styles from './styles.module.css'; +import styles from './index.module.css'; import {useDocsSidebar} from '@docusaurus/theme-common'; @@ -24,7 +24,7 @@ export default function DocPageLayout({children}: Props): JSX.Element {
{sidebar && ( - - matchPath(location.pathname, docRoute), - ); - if (!currentDocRoute) { - return null; - } - - // For now, the sidebarName is added as route config: not ideal! - const sidebarName = currentDocRoute.sidebar; - - const sidebarItems = sidebarName - ? versionMetadata.docsSidebars[sidebarName] - : undefined; - - const docElement = renderRoutes(props.route.routes, { - versionMetadata, - }); - - return { - docElement, - sidebarName, - sidebarItems, - }; -} - export default function DocPage(props: Props): JSX.Element { const {versionMetadata} = props; - const currentDocRouteMetadata = extractDocRouteMetadata(props); + const currentDocRouteMetadata = useDocRouteMetadata(props); if (!currentDocRouteMetadata) { return ; } diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts index 38a0486fc10c..d086b65426b6 100644 --- a/packages/docusaurus-theme-common/src/index.ts +++ b/packages/docusaurus-theme-common/src/index.ts @@ -55,6 +55,7 @@ export { useDocsVersionCandidates, useLayoutDoc, useLayoutDocsSidebar, + useDocRouteMetadata, } from './utils/docsUtils'; export {useSkipToContent} from './utils/a11yUtils'; diff --git a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx index 8ee82d5eb2e4..3927cc6b9e3d 100644 --- a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx +++ b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx @@ -20,6 +20,7 @@ import type { PropSidebarItem, PropSidebarItemCategory, PropVersionDoc, + PropVersionMetadata, PropSidebarBreadcrumbsItem, } from '@docusaurus/plugin-content-docs'; import {useDocsPreferredVersion} from '../contexts/docsPreferredVersion'; @@ -27,7 +28,9 @@ import {useDocsVersion} from '../contexts/docsVersion'; import {useDocsSidebar} from '../contexts/docsSidebar'; import {uniq} from './jsUtils'; import {isSamePath} from './routesUtils'; -import {useLocation} from '@docusaurus/router'; +import {matchPath, useLocation} from '@docusaurus/router'; +import renderRoutes from '@docusaurus/renderRoutes'; +import type {RouteConfig} from 'react-router-config'; // TODO not ideal, see also "useDocs" export const isDocsPluginEnabled: boolean = !!useAllDocsData; @@ -281,3 +284,42 @@ Available doc ids are: return doc; }, [docId, versions]); } + +// TODO later read version/route directly from context +export function useDocRouteMetadata({ + route, + versionMetadata, +}: { + route: RouteConfig; + versionMetadata: PropVersionMetadata; +}): null | { + docElement: JSX.Element; + sidebarName: string | undefined; + sidebarItems: PropSidebar | undefined; +} { + const location = useLocation(); + const docRoutes = route.routes; + const currentDocRoute = docRoutes!.find((docRoute) => + matchPath(location.pathname, docRoute), + ); + if (!currentDocRoute) { + return null; + } + + // For now, the sidebarName is added as route config: not ideal! + const sidebarName = currentDocRoute.sidebar; + + const sidebarItems = sidebarName + ? versionMetadata.docsSidebars[sidebarName] + : undefined; + + const docElement = renderRoutes(route.routes!, { + versionMetadata, + }); + + return { + docElement, + sidebarName, + sidebarItems, + }; +}