diff --git a/.changeset/crosslinks.md b/.changeset/crosslinks.md new file mode 100644 index 00000000..a633e0d5 --- /dev/null +++ b/.changeset/crosslinks.md @@ -0,0 +1,5 @@ +--- +'@doc-kit/generator-react': patch +--- + +Adds support for cross-links, opt-in with `showCrossLinks: true` diff --git a/packages/react/src/html/index.mjs b/packages/react/src/html/index.mjs index 461e6387..4f09bf6b 100644 --- a/packages/react/src/html/index.mjs +++ b/packages/react/src/html/index.mjs @@ -74,7 +74,12 @@ export default { components: {}, // The SideBar and NavBar navigation items - navigation: {}, + // along with other navigational settings (e.g. showCrossLinks) + navigation: { + // Whether or not to show the CrossLink component at the bottom of the + // default layout. + showCrossLinks: false, + }, // When omitted, the Vite adapter is loaded lazily during generation. bundler: undefined, diff --git a/packages/react/src/html/types.d.ts b/packages/react/src/html/types.d.ts index c0ac4cfd..b79297f8 100644 --- a/packages/react/src/html/types.d.ts +++ b/packages/react/src/html/types.d.ts @@ -77,7 +77,7 @@ export type Configuration = { navigation: { sidebar?: ComponentProps['groups']; navbar?: ComponentProps['navItems']; - // TODO(@avivkeller): `navigation.showCrossLinks` + showCrossLinks?: boolean; }; // Optional bundler adapter. When omitted, the Vite adapter is loaded lazily. bundler?: WebBundler; diff --git a/packages/react/src/html/ui/components/Layout/index.jsx b/packages/react/src/html/ui/components/Layout/index.jsx index 7b0c243c..6308aa74 100644 --- a/packages/react/src/html/ui/components/Layout/index.jsx +++ b/packages/react/src/html/ui/components/Layout/index.jsx @@ -1,8 +1,11 @@ +import CrossLink from '@node-core/ui-components/Common/BaseCrossLink'; import TableOfContents from '@node-core/ui-components/Common/TableOfContents'; import Article from '@node-core/ui-components/Containers/Article'; import Banner from '../Banner'; +import styles from './index.module.css'; +import { navigation } from '#theme/config'; import Footer from '#theme/Footer'; import MetaBar from '#theme/Metabar'; import NavBar from '#theme/Navigation'; @@ -17,25 +20,61 @@ import SideBar from '#theme/Sidebar'; * * @param {{ metadata: import('../../types').SerializedMetadata, headings: Array, readingTime: string, children: import('preact').ComponentChildren }} props */ -export default ({ metadata, headings, readingTime, children }) => ( - <> - - -
- -
+export default ({ metadata, headings, readingTime, children }) => { + const crossLinkItems = navigation.showCrossLinks + ? (navigation.sidebar?.flatMap(({ items }) => items) ?? []) + : []; + + const currentItem = crossLinkItems.findIndex( + ({ link }) => link === metadata.path + ); + + const [previousCrossLink, nextCrossLink] = [ + crossLinkItems[currentItem - 1], + crossLinkItems[currentItem + 1], + ]; + + return ( + <> + + +
+
- -
-
{children}
+
+ +
+
{children}
+ {(previousCrossLink || nextCrossLink) && ( +
+ {(previousCrossLink && ( + + )) ||
} + + {nextCrossLink && ( + + )} +
+ )} +
+
- -
-
-
- -); +
+