diff --git a/packages/docusaurus-theme-classic/src/theme/TabItem/index.tsx b/packages/docusaurus-theme-classic/src/theme/TabItem/index.tsx index 99559b36e6ae..c841302fb442 100644 --- a/packages/docusaurus-theme-classic/src/theme/TabItem/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/TabItem/index.tsx @@ -8,8 +8,12 @@ import React from 'react'; import type {Props} from '@theme/TabItem'; -function TabItem(props: Props): JSX.Element { - return
{props.children}
; +function TabItem({children, hidden, className}: Props): JSX.Element { + return ( +
+ {children} +
+ ); } export default TabItem; diff --git a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx index 4b84a76523fc..7616a73c5074 100644 --- a/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx +++ b/packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import React, {useState, Children, ReactElement} from 'react'; +import React, {useState, cloneElement} from 'react'; import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext'; import type {Props} from '@theme/Tabs'; @@ -19,7 +19,15 @@ const keys = { }; function Tabs(props: Props): JSX.Element { - const {block, children, defaultValue, values, groupId, className} = props; + const { + lazy, + block, + children, + defaultValue, + values, + groupId, + className, + } = props; const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext(); const [selectedValue, setSelectedValue] = useState(defaultValue); @@ -109,15 +117,24 @@ function Tabs(props: Props): JSX.Element { ))} -
- { - Children.toArray(children).filter( - (child) => - (child as ReactElement<{value: string}>).props.value === - selectedValue, - )[0] - } -
+ + {lazy ? ( + cloneElement( + children.filter( + (tabItem) => tabItem.props.value === selectedValue, + )[0], + {className: 'margin-vert--md'}, + ) + ) : ( +
+ {children.map((tabItem, i) => + cloneElement(tabItem, { + key: i, + hidden: tabItem.props.value !== selectedValue, + }), + )} +
+ )} ); } diff --git a/packages/docusaurus-theme-classic/src/types.d.ts b/packages/docusaurus-theme-classic/src/types.d.ts index c6bf4dbc3f81..122b65cdc5d1 100644 --- a/packages/docusaurus-theme-classic/src/types.d.ts +++ b/packages/docusaurus-theme-classic/src/types.d.ts @@ -374,7 +374,12 @@ declare module '@theme/NavbarItem' { declare module '@theme/TabItem' { import type {ReactNode} from 'react'; - export type Props = {readonly children: ReactNode}; + export type Props = { + readonly children: ReactNode; + readonly value: string; + readonly hidden: boolean; + readonly className: string; + }; const TabItem: () => JSX.Element; export default TabItem; @@ -382,10 +387,12 @@ declare module '@theme/TabItem' { declare module '@theme/Tabs' { import type {ReactElement} from 'react'; + import type {Props as TabItemProps} from '@theme/TabItem'; export type Props = { + readonly lazy?: boolean; readonly block?: boolean; - readonly children: readonly ReactElement<{value: string}>[]; + readonly children: readonly ReactElement[]; readonly defaultValue?: string; readonly values: readonly {value: string; label: string}[]; readonly groupId?: string; diff --git a/website/docs/markdown-features.mdx b/website/docs/markdown-features.mdx index ba5274813ae5..c07cc999467c 100644 --- a/website/docs/markdown-features.mdx +++ b/website/docs/markdown-features.mdx @@ -296,6 +296,12 @@ And you will get the following: This is a banana 🍌 +:::info + +By default, tabs are rendered eagerly, but it is possible to load them lazily by passing the `lazy` prop to the `Tabs` component. + +::: + ### Syncing tab choices You may want choices of the same kind of tabs to sync with each other. For example, you might want to provide different instructions for users on Windows vs users on macOS, and you want to changing all OS-specific instructions tabs in one click. To achieve that, you can give all related tabs the same `groupId` prop. Note that doing this will persist the choice in `localStorage` and all `` instances with the same `groupId` will update automatically when the value of one of them is changed. Not that `groupID` are globally-namespaced.