fix: render mobile toc after page title

This commit is contained in:
Hossein Mehrabi
2023-06-09 04:11:02 +03:30
parent bee5df33fb
commit 88cc89fcee
6 changed files with 90 additions and 13 deletions
@@ -0,0 +1,36 @@
import React, { useContext, useMemo } from 'react'
export type MDXComponentType = 'heading'
export type MDXEnhancementPosition = 'after'
export type MDXEnhancementItem = {
component: MDXComponentType
position: MDXEnhancementPosition
render: (props: any) => React.ReactNode
}
export type MDXEnhancementContextType = {
items: MDXEnhancementItem[]
}
export const MDXEnhancementContext =
React.createContext<MDXEnhancementContextType>({
items: [],
})
export const useMDXEnhancementElements = <T = any>(
component: MDXComponentType,
position: MDXEnhancementPosition,
props: T,
): React.ReactNode => {
const ctx = useContext(MDXEnhancementContext)
if (!ctx) return []
return useMemo(() => {
const items = ctx.items.filter(
(item) => item.component === component && item.position === position,
)
return items.map((item) => item.render(props))
}, [component, position, props])
}
@@ -0,0 +1 @@
export * from './MDXEnhancement.context'
@@ -4,6 +4,7 @@ import { ThemeClassNames } from '@docusaurus/theme-common'
import { useDoc } from '@docusaurus/theme-common/internal'
import Heading from '@theme/Heading'
import MDXContent from '@theme/MDXContent'
import MDXHeading from '@theme/MDXComponents/Heading'
/**
Title can be declared inside md content or declared through
front matter and added manually. To make both cases consistent,
@@ -29,7 +30,7 @@ export default function DocItemContent({ children }) {
<div className={clsx(ThemeClassNames.docs.docMarkdown, 'markdown')}>
{syntheticTitle && (
<header>
<Heading as="h1">{syntheticTitle}</Heading>
<MDXHeading as="h1">{syntheticTitle}</MDXHeading>
</header>
)}
<MDXContent>{children}</MDXContent>
@@ -1,17 +1,19 @@
import React from 'react'
import clsx from 'clsx'
import { useWindowSize } from '@docusaurus/theme-common'
import { useDoc } from '@docusaurus/theme-common/internal'
import DocItemPaginator from '@theme/DocItem/Paginator'
import DocVersionBanner from '@theme/DocVersionBanner'
import DocVersionBadge from '@theme/DocVersionBadge'
import DocItemFooter from '@theme/DocItem/Footer'
import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile'
import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop'
import DocItemContent from '@theme/DocItem/Content'
import DocBreadcrumbs from '@theme/DocBreadcrumbs'
import styles from './styles.module.scss'
import DocItemContent from '@theme/DocItem/Content'
import DocItemFooter from '@theme/DocItem/Footer'
import DocItemPaginator from '@theme/DocItem/Paginator'
import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop'
import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile'
import DocVersionBadge from '@theme/DocVersionBadge'
import DocVersionBanner from '@theme/DocVersionBanner'
import { Props as HeadingProps } from '@theme/Heading'
import clsx from 'clsx'
import React from 'react'
import { useMedia } from 'react-use'
import { MDXEnhancementContext } from '../../../containers/MDXEnhacement/MDXEnhancement.context'
import styles from './styles.module.scss'
/**
* Decide if the toc should be rendered, on mobile or desktop viewports
@@ -50,8 +52,20 @@ export default function DocItemLayout({ children }) {
<article>
<DocBreadcrumbs />
<DocVersionBadge />
{docTOC.mobile}
<DocItemContent>{children}</DocItemContent>
<MDXEnhancementContext.Provider
value={{
items: [
{
component: 'heading',
position: 'after',
render: (props: HeadingProps) =>
props.as === 'h1' && docTOC.mobile,
},
],
}}
>
<DocItemContent>{children}</DocItemContent>
</MDXEnhancementContext.Provider>
<DocItemFooter />
</article>
<DocItemPaginator />
@@ -20,8 +20,18 @@
}
.tocMobile {
margin-top: -0.5rem;
margin-bottom: 2rem;
& > div {
display: block !important;
margin: 0;
}
}
.docItemContainer {
.tocMobile:not(:first-of-type) {
display: none;
}
}
@@ -0,0 +1,15 @@
import Heading from '@docusaurus/theme-classic/lib/theme/MDXComponents/Heading'
import type { Props } from '@theme/MDXComponents/Heading'
import React from 'react'
import { useMDXEnhancementElements } from '../../containers/MDXEnhacement/MDXEnhancement.context'
export default function MDXHeading(props: Props): JSX.Element {
const after = useMDXEnhancementElements('heading', 'after', props)
return (
<>
<Heading {...props} />
{after}
</>
)
}