mirror of
https://github.com/facebook/docusaurus.git
synced 2025-12-26 09:43:10 +00:00
refactor(theme-classic): refactor TOC-related theme components (#7270)
* extract TOCItemTree component * refactor TOCCollapsible
This commit is contained in:
parent
3bef88232f
commit
e053f39cf0
|
|
@ -1061,6 +1061,19 @@ declare module '@theme/TOCItems' {
|
|||
export default function TOCItems(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/TOCItems/Tree' {
|
||||
import type {TOCTreeNode} from '@docusaurus/theme-common';
|
||||
|
||||
export interface Props {
|
||||
readonly toc: readonly TOCTreeNode[];
|
||||
readonly className: string;
|
||||
readonly linkClassName: string | null;
|
||||
readonly isChild?: boolean;
|
||||
}
|
||||
|
||||
export default function TOCItems(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/TOC' {
|
||||
import type {TOCItem} from '@docusaurus/types';
|
||||
|
||||
|
|
@ -1101,6 +1114,18 @@ declare module '@theme/TOCCollapsible' {
|
|||
export default function TOCCollapsible(props: Props): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/TOCCollapsible/CollapseButton' {
|
||||
import type {ComponentProps} from 'react';
|
||||
|
||||
export interface Props extends ComponentProps<'button'> {
|
||||
collapsed: boolean;
|
||||
}
|
||||
|
||||
export default function TOCCollapsibleCollapseButton(
|
||||
props: Props,
|
||||
): JSX.Element;
|
||||
}
|
||||
|
||||
declare module '@theme/ColorModeToggle' {
|
||||
import type {ColorMode} from '@docusaurus/theme-common';
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,6 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
.tocCollapsible {
|
||||
background-color: var(--ifm-menu-color-background-active);
|
||||
border-radius: var(--ifm-global-radius);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.tocCollapsibleButton {
|
||||
font-size: inherit;
|
||||
display: flex;
|
||||
|
|
@ -30,21 +24,6 @@
|
|||
transition: transform var(--ifm-transition-fast);
|
||||
}
|
||||
|
||||
.tocCollapsibleContent > ul {
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--ifm-color-emphasis-300);
|
||||
padding: 0.2rem 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tocCollapsibleContent ul li {
|
||||
margin: 0.4rem 0.8rem;
|
||||
}
|
||||
|
||||
.tocCollapsibleContent a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tocCollapsibleExpanded .tocCollapsibleButton::after {
|
||||
.tocCollapsibleButtonExpanded::after {
|
||||
transform: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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 clsx from 'clsx';
|
||||
import Translate from '@docusaurus/Translate';
|
||||
import styles from './CollapseButton.module.css';
|
||||
import type {Props} from '@theme/TOCCollapsible/CollapseButton';
|
||||
|
||||
export default function TOCCollapsibleCollapseButton({
|
||||
collapsed,
|
||||
...props
|
||||
}: Props): JSX.Element {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
{...props}
|
||||
className={clsx(
|
||||
'clean-btn',
|
||||
styles.tocCollapsibleButton,
|
||||
!collapsed && styles.tocCollapsibleButtonExpanded,
|
||||
props.className,
|
||||
)}>
|
||||
<Translate
|
||||
id="theme.TOCCollapsible.toggleButtonLabel"
|
||||
description="The label used by the button on the collapsible TOC component">
|
||||
On this page
|
||||
</Translate>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.tocCollapsible {
|
||||
background-color: var(--ifm-menu-color-background-active);
|
||||
border-radius: var(--ifm-global-radius);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.tocCollapsibleContent > ul {
|
||||
border-left: none;
|
||||
border-top: 1px solid var(--ifm-color-emphasis-300);
|
||||
padding: 0.2rem 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.tocCollapsibleContent ul li {
|
||||
margin: 0.4rem 0.8rem;
|
||||
}
|
||||
|
||||
.tocCollapsibleContent a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tocCollapsibleExpanded {
|
||||
transform: none;
|
||||
}
|
||||
|
|
@ -7,11 +7,11 @@
|
|||
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Translate from '@docusaurus/Translate';
|
||||
import {useCollapsible, Collapsible} from '@docusaurus/theme-common';
|
||||
import styles from './styles.module.css';
|
||||
import styles from './index.module.css';
|
||||
import TOCItems from '@theme/TOCItems';
|
||||
import type {Props} from '@theme/TOCCollapsible';
|
||||
import CollapseButton from '@theme/TOCCollapsible/CollapseButton';
|
||||
|
||||
export default function TOCCollapsible({
|
||||
toc,
|
||||
|
|
@ -22,7 +22,6 @@ export default function TOCCollapsible({
|
|||
const {collapsed, toggleCollapsed} = useCollapsible({
|
||||
initialState: true,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
|
|
@ -30,17 +29,7 @@ export default function TOCCollapsible({
|
|||
!collapsed && styles.tocCollapsibleExpanded,
|
||||
className,
|
||||
)}>
|
||||
<button
|
||||
type="button"
|
||||
className={clsx('clean-btn', styles.tocCollapsibleButton)}
|
||||
onClick={toggleCollapsed}>
|
||||
<Translate
|
||||
id="theme.TOCCollapsible.toggleButtonLabel"
|
||||
description="The label used by the button on the collapsible TOC component">
|
||||
On this page
|
||||
</Translate>
|
||||
</button>
|
||||
|
||||
<CollapseButton collapsed={collapsed} onClick={toggleCollapsed} />
|
||||
<Collapsible
|
||||
lazy
|
||||
className={styles.tocCollapsibleContent}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 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 type {Props} from '@theme/TOCItems/Tree';
|
||||
|
||||
// Recursive component rendering the toc tree
|
||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||
function TOCItemTree({
|
||||
toc,
|
||||
className,
|
||||
linkClassName,
|
||||
isChild,
|
||||
}: Props): JSX.Element | null {
|
||||
if (!toc.length) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ul className={isChild ? undefined : className}>
|
||||
{toc.map((heading) => (
|
||||
<li key={heading.id}>
|
||||
<a
|
||||
href={`#${heading.id}`}
|
||||
className={linkClassName ?? undefined}
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{__html: heading.value}}
|
||||
/>
|
||||
<TOCItemTree
|
||||
isChild
|
||||
toc={heading.children}
|
||||
className={className}
|
||||
linkClassName={linkClassName}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
// Memo only the tree root is enough
|
||||
export default React.memo(TOCItemTree);
|
||||
|
|
@ -7,53 +7,14 @@
|
|||
|
||||
import React, {useMemo} from 'react';
|
||||
import type {Props} from '@theme/TOCItems';
|
||||
import TOCItemTree from '@theme/TOCItems/Tree';
|
||||
import {
|
||||
type TOCHighlightConfig,
|
||||
type TOCTreeNode,
|
||||
useThemeConfig,
|
||||
useTOCHighlight,
|
||||
useFilteredAndTreeifiedTOC,
|
||||
} from '@docusaurus/theme-common';
|
||||
|
||||
// Recursive component rendering the toc tree
|
||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||
function TOCItemList({
|
||||
toc,
|
||||
className,
|
||||
linkClassName,
|
||||
isChild,
|
||||
}: {
|
||||
readonly toc: readonly TOCTreeNode[];
|
||||
readonly className: string;
|
||||
readonly linkClassName: string | null;
|
||||
readonly isChild?: boolean;
|
||||
}): JSX.Element | null {
|
||||
if (!toc.length) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ul className={isChild ? undefined : className}>
|
||||
{toc.map((heading) => (
|
||||
<li key={heading.id}>
|
||||
<a
|
||||
href={`#${heading.id}`}
|
||||
className={linkClassName ?? undefined}
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{__html: heading.value}}
|
||||
/>
|
||||
<TOCItemList
|
||||
isChild
|
||||
toc={heading.children}
|
||||
className={className}
|
||||
linkClassName={linkClassName}
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
export default function TOCItems({
|
||||
toc,
|
||||
className = 'table-of-contents table-of-contents__left-border',
|
||||
|
|
@ -90,7 +51,7 @@ export default function TOCItems({
|
|||
useTOCHighlight(tocHighlightConfig);
|
||||
|
||||
return (
|
||||
<TOCItemList
|
||||
<TOCItemTree
|
||||
toc={tocTree}
|
||||
className={className}
|
||||
linkClassName={linkClassName}
|
||||
|
|
|
|||
Loading…
Reference in New Issue