From 2964e6f65d3621af5516b66a0ca1aab25f5100ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Fri, 25 Mar 2022 18:59:31 +0100 Subject: [PATCH] refactor: split DocSidebarItem by item type (#7005) --- .../src/plugin-content-docs.d.ts | 2 + .../src/theme-classic.d.ts | 34 +++ .../src/theme/DocSidebarItem/Category.tsx | 212 ++++++++++++++ .../{styles.module.css => Html.module.css} | 4 - .../src/theme/DocSidebarItem/Html.tsx | 34 +++ .../src/theme/DocSidebarItem/Link.module.css | 10 + .../src/theme/DocSidebarItem/Link.tsx | 58 ++++ .../src/theme/DocSidebarItem/index.tsx | 263 +----------------- 8 files changed, 354 insertions(+), 263 deletions(-) create mode 100644 packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category.tsx rename packages/docusaurus-theme-classic/src/theme/DocSidebarItem/{styles.module.css => Html.module.css} (88%) create mode 100644 packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Html.tsx create mode 100644 packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link.module.css create mode 100644 packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Link.tsx 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 3d3898e0cf86..ad361efcb4ea 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 @@ -134,6 +134,8 @@ declare module '@docusaurus/plugin-content-docs' { export type PropSidebarItemLink = import('./sidebars/types').PropSidebarItemLink; + export type PropSidebarItemHtml = + import('./sidebars/types').PropSidebarItemHtml; export type PropSidebarItemCategory = import('./sidebars/types').PropSidebarItemCategory; export type PropSidebarItem = import('./sidebars/types').PropSidebarItem; diff --git a/packages/docusaurus-theme-classic/src/theme-classic.d.ts b/packages/docusaurus-theme-classic/src/theme-classic.d.ts index 440eb8bbfc41..bb3e03137640 100644 --- a/packages/docusaurus-theme-classic/src/theme-classic.d.ts +++ b/packages/docusaurus-theme-classic/src/theme-classic.d.ts @@ -235,6 +235,40 @@ declare module '@theme/DocSidebarItem' { export default function DocSidebarItem(props: Props): JSX.Element; } +declare module '@theme/DocSidebarItem/Link' { + import type {Props as DocSidebarItemProps} from '@theme/DocSidebarItem'; + + import type {PropSidebarItemLink} from '@docusaurus/plugin-content-docs'; + + export interface Props extends DocSidebarItemProps { + item: PropSidebarItemLink; + } + + export default function DocSidebarItemLink(props: Props): JSX.Element; +} + +declare module '@theme/DocSidebarItem/Html' { + import type {Props as DocSidebarItemProps} from '@theme/DocSidebarItem'; + import type {PropSidebarItemHtml} from '@docusaurus/plugin-content-docs'; + + export interface Props extends DocSidebarItemProps { + item: PropSidebarItemHtml; + } + + export default function DocSidebarItemHtml(props: Props): JSX.Element; +} + +declare module '@theme/DocSidebarItem/Category' { + import type {Props as DocSidebarItemProps} from '@theme/DocSidebarItem'; + import type {PropSidebarItemCategory} from '@docusaurus/plugin-content-docs'; + + export interface Props extends DocSidebarItemProps { + item: PropSidebarItemCategory; + } + + export default function DocSidebarItemCategory(props: Props): JSX.Element; +} + declare module '@theme/DocSidebarItems' { import type {Props as DocSidebarItemProps} from '@theme/DocSidebarItem'; import type {PropSidebarItem} from '@docusaurus/plugin-content-docs'; diff --git a/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category.tsx b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category.tsx new file mode 100644 index 000000000000..c75cf9d7c99a --- /dev/null +++ b/packages/docusaurus-theme-classic/src/theme/DocSidebarItem/Category.tsx @@ -0,0 +1,212 @@ +/** + * 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, {type ComponentProps, useEffect, useMemo} from 'react'; +import clsx from 'clsx'; +import { + isActiveSidebarItem, + usePrevious, + Collapsible, + useCollapsible, + findFirstCategoryLink, + ThemeClassNames, + useThemeConfig, + useDocSidebarItemsExpandedState, + isSamePath, +} from '@docusaurus/theme-common'; +import Link from '@docusaurus/Link'; +import {translate} from '@docusaurus/Translate'; + +import DocSidebarItems from '@theme/DocSidebarItems'; +import type {Props} from '@theme/DocSidebarItem/Category'; + +import useIsBrowser from '@docusaurus/useIsBrowser'; + +// If we navigate to a category and it becomes active, it should automatically +// expand itself +function useAutoExpandActiveCategory({ + isActive, + collapsed, + setCollapsed, +}: { + isActive: boolean; + collapsed: boolean; + setCollapsed: (b: boolean) => void; +}) { + const wasActive = usePrevious(isActive); + useEffect(() => { + const justBecameActive = isActive && !wasActive; + if (justBecameActive && collapsed) { + setCollapsed(false); + } + }, [isActive, wasActive, collapsed, setCollapsed]); +} + +/** + * When a collapsible category has no link, we still link it to its first child + * during SSR as a temporary fallback. This allows to be able to navigate inside + * the category even when JS fails to load, is delayed or simply disabled + * React hydration becomes an optional progressive enhancement + * see https://github.com/facebookincubator/infima/issues/36#issuecomment-772543188 + * see https://github.com/facebook/docusaurus/issues/3030 + */ +function useCategoryHrefWithSSRFallback( + item: Props['item'], +): string | undefined { + const isBrowser = useIsBrowser(); + return useMemo(() => { + if (item.href) { + return item.href; + } + // In these cases, it's not necessary to render a fallback + // We skip the "findFirstCategoryLink" computation + if (isBrowser || !item.collapsible) { + return undefined; + } + return findFirstCategoryLink(item); + }, [item, isBrowser]); +} + +function CollapseButton({ + categoryLabel, + onClick, +}: { + categoryLabel: string; + onClick: ComponentProps<'button'>['onClick']; +}) { + return ( +