diff --git a/docs/waterfall/README.mdx b/docs/waterfall/README.mdx index 545063f25..92510df50 100644 --- a/docs/waterfall/README.mdx +++ b/docs/waterfall/README.mdx @@ -1,3 +1,8 @@ +--- +sunsetted: true +sunsettingMessage: We recommend you transition to Velocity. +--- + import DocCardList from "@theme/DocCardList"; import { useCurrentSidebarCategory } from "@docusaurus/theme-common"; diff --git a/docs/waterfall/configuration.mdx b/docs/waterfall/configuration.mdx index 4aa6bd1c9..a81f27b8b 100644 --- a/docs/waterfall/configuration.mdx +++ b/docs/waterfall/configuration.mdx @@ -1,6 +1,8 @@ --- slug: /configuration description: Configuration guide for Waterfall. +sunsetted: true +sunsettingMessage: We recommend you transition to Velocity. --- import React from 'react'; diff --git a/docs/waterfall/getting-started.md b/docs/waterfall/getting-started.md index c3279564c..4145f4090 100644 --- a/docs/waterfall/getting-started.md +++ b/docs/waterfall/getting-started.md @@ -1,6 +1,8 @@ --- slug: /getting-started description: How to get started with running Waterfall. +sunsetted: true +sunsettingMessage: We recommend you transition to Velocity. --- # Getting Started diff --git a/src/css/custom.css b/src/css/custom.css index 0695f81eb..9d4a90fd8 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -31,6 +31,18 @@ html[data-theme="dark"] { --config-node-highlight-text-color: white; } +.sunset-message { + width: 100%; + height: 5rem; + margin: 20px 0 20px 0; + display: flex; + align-items: center; + justify-content: center; + border-radius: 8px; + border: 4px solid rgb(101 38 0); + background-color: #853200; +} + .button.button--secondary { color: #f6f7f8; } diff --git a/src/theme/DocItem/Content/index.tsx b/src/theme/DocItem/Content/index.tsx new file mode 100644 index 000000000..488823d77 --- /dev/null +++ b/src/theme/DocItem/Content/index.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import clsx from 'clsx'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import {useDoc} from '@docusaurus/theme-common/internal'; +import Heading from '@theme/Heading'; +import MDXContent from '@theme/MDXContent'; +import type {Props} from '@theme/DocItem/Content'; + +/** + Title can be declared inside md content or declared through + front matter and added manually. To make both cases consistent, + the added title is added under the same div.markdown block + See https://github.com/facebook/docusaurus/pull/4882#issuecomment-853021120 + + We render a "synthetic title" if: + - user doesn't ask to hide it with front matter + - the markdown content does not already contain a top-level h1 heading +*/ +function useSyntheticTitle(): string | null { + const {metadata, frontMatter, contentTitle} = useDoc(); + const shouldRender = + !frontMatter.hide_title && typeof contentTitle === 'undefined'; + if (!shouldRender) { + return null; + } + return metadata.title; +} + +export default function DocItemContent({children}: Props): JSX.Element { + const syntheticTitle = useSyntheticTitle(); + return ( +
+ {syntheticTitle && ( +
+ {syntheticTitle} +
+ )} + {children} +
+ ); +} diff --git a/src/theme/DocItem/Footer/index.tsx b/src/theme/DocItem/Footer/index.tsx new file mode 100644 index 000000000..bd29e2234 --- /dev/null +++ b/src/theme/DocItem/Footer/index.tsx @@ -0,0 +1,82 @@ +import React from 'react'; +import clsx from 'clsx'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import {useDoc, type DocContextValue} from '@docusaurus/theme-common/internal'; +import LastUpdated from '@theme/LastUpdated'; +import EditThisPage from '@theme/EditThisPage'; +import TagsListInline, { + type Props as TagsListInlineProps, +} from '@theme/TagsListInline'; + +import styles from './styles.module.css'; + +function TagsRow(props: TagsListInlineProps) { + return ( +
+
+ +
+
+ ); +} + +type EditMetaRowProps = Pick< + DocContextValue['metadata'], + 'editUrl' | 'lastUpdatedAt' | 'lastUpdatedBy' | 'formattedLastUpdatedAt' +>; +function EditMetaRow({ + editUrl, + lastUpdatedAt, + lastUpdatedBy, + formattedLastUpdatedAt, +}: EditMetaRowProps) { + return ( +
+
{editUrl && }
+ +
+ {(lastUpdatedAt || lastUpdatedBy) && ( + + )} +
+
+ ); +} + +export default function DocItemFooter(): JSX.Element | null { + const {metadata} = useDoc(); + const {editUrl, lastUpdatedAt, formattedLastUpdatedAt, lastUpdatedBy, tags} = + metadata; + + const canDisplayTagsRow = tags.length > 0; + const canDisplayEditMetaRow = !!(editUrl || lastUpdatedAt || lastUpdatedBy); + + const canDisplayFooter = canDisplayTagsRow || canDisplayEditMetaRow; + + if (!canDisplayFooter) { + return null; + } + + return ( + + ); +} diff --git a/src/theme/DocItem/Footer/styles.module.css b/src/theme/DocItem/Footer/styles.module.css new file mode 100644 index 000000000..7c1e96441 --- /dev/null +++ b/src/theme/DocItem/Footer/styles.module.css @@ -0,0 +1,11 @@ +.lastUpdated { + margin-top: 0.2rem; + font-style: italic; + font-size: smaller; +} + +@media (min-width: 997px) { + .lastUpdated { + text-align: right; + } +} diff --git a/src/theme/DocItem/Layout/index.tsx b/src/theme/DocItem/Layout/index.tsx new file mode 100644 index 000000000..dd36bcab0 --- /dev/null +++ b/src/theme/DocItem/Layout/index.tsx @@ -0,0 +1,66 @@ +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 Unlisted from '@theme/Unlisted'; +import type {Props} from '@theme/DocItem/Layout'; + +import styles from './styles.module.css'; + +/** + * Decide if the toc should be rendered, on mobile or desktop viewports + */ +function useDocTOC() { + const {frontMatter, toc} = useDoc(); + const windowSize = useWindowSize(); + + const hidden = frontMatter.hide_table_of_contents; + const canRender = !hidden && toc.length > 0; + + const mobile = canRender ? : undefined; + + const desktop = + canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? ( + + ) : undefined; + + return { + hidden, + mobile, + desktop, + }; +} + +export default function DocItemLayout({children}: Props): JSX.Element { + const docTOC = useDocTOC(); + const { + metadata: {unlisted}, + } = useDoc(); + return ( +
+
+ {unlisted && } + +
+
+ + + {docTOC.mobile} + {children} + +
+ +
+
+ {docTOC.desktop &&
{docTOC.desktop}
} +
+ ); +} diff --git a/src/theme/DocItem/Layout/styles.module.css b/src/theme/DocItem/Layout/styles.module.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/theme/DocItem/Metadata/index.tsx b/src/theme/DocItem/Metadata/index.tsx new file mode 100644 index 000000000..cd7b9b5cb --- /dev/null +++ b/src/theme/DocItem/Metadata/index.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import {PageMetadata} from '@docusaurus/theme-common'; +import {useDoc} from '@docusaurus/theme-common/internal'; + +export default function DocItemMetadata(): JSX.Element { + const {metadata, frontMatter, assets} = useDoc(); + return ( + + ); +} diff --git a/src/theme/DocItem/Paginator/index.tsx b/src/theme/DocItem/Paginator/index.tsx new file mode 100644 index 000000000..a2b3ae0b9 --- /dev/null +++ b/src/theme/DocItem/Paginator/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import {useDoc} from '@docusaurus/theme-common/internal'; +import DocPaginator from '@theme/DocPaginator'; + +/** + * This extra component is needed, because should remain generic. + * DocPaginator is used in non-docs contexts too: generated-index pages... + */ +export default function DocItemPaginator(): JSX.Element { + const {metadata} = useDoc(); + return ; +} diff --git a/src/theme/DocItem/TOC/Desktop/index.tsx b/src/theme/DocItem/TOC/Desktop/index.tsx new file mode 100644 index 000000000..4b555e6e5 --- /dev/null +++ b/src/theme/DocItem/TOC/Desktop/index.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import {useDoc} from '@docusaurus/theme-common/internal'; + +import TOC from '@theme/TOC'; + +export default function DocItemTOCDesktop(): JSX.Element { + const {toc, frontMatter} = useDoc(); + return ( + + ); +} diff --git a/src/theme/DocItem/TOC/Mobile/index.tsx b/src/theme/DocItem/TOC/Mobile/index.tsx new file mode 100644 index 000000000..4e6db293c --- /dev/null +++ b/src/theme/DocItem/TOC/Mobile/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import clsx from 'clsx'; +import {ThemeClassNames} from '@docusaurus/theme-common'; +import {useDoc} from '@docusaurus/theme-common/internal'; + +import TOCCollapsible from '@theme/TOCCollapsible'; + +import styles from './styles.module.css'; + +export default function DocItemTOCMobile(): JSX.Element { + const {toc, frontMatter} = useDoc(); + return ( + + ); +} diff --git a/src/theme/DocItem/TOC/Mobile/styles.module.css b/src/theme/DocItem/TOC/Mobile/styles.module.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/theme/DocItem/index.tsx b/src/theme/DocItem/index.tsx new file mode 100644 index 000000000..639d1c001 --- /dev/null +++ b/src/theme/DocItem/index.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import {HtmlClassNameProvider} from '@docusaurus/theme-common'; +import {DocProvider} from '@docusaurus/theme-common/internal'; +import DocItemMetadata from '@theme/DocItem/Metadata'; +import DocItemLayout from '@theme/DocItem/Layout'; +import type {Props} from '@theme/DocItem'; + +function SunsettedPage(message: string) { + return ( +
+ + {message} + +
+ ); +} + +export default function DocItem(props: Props): JSX.Element { + const docHtmlClassName = `docs-doc-id-${props.content.metadata.id}`; + const MDXComponent = props.content; + const sunsettedPage = props.content?.frontMatter?.sunsetted === true; + const sunsettingMessage = "This project has been sunsetted and is no longer maintained. " + props.content?.frontMatter?.sunsettingMessage || ""; + + return ( + + + + + <> + { + sunsettedPage && SunsettedPage(sunsettingMessage) + } + + + + + + ); +}