From 78b7253bb45a48c3e98e7c5f542962ce411a125b Mon Sep 17 00:00:00 2001 From: avivkeller Date: Fri, 7 Aug 2026 20:24:07 -0400 Subject: [PATCH 1/3] feat: cross links Signed-off-by: avivkeller --- .changeset/crosslinks.md | 5 ++ packages/react/src/html/index.mjs | 7 +- packages/react/src/html/types.d.ts | 2 +- .../src/html/ui/components/Layout/index.jsx | 75 ++++++++++++++----- .../ui/components/Layout/index.module.css | 13 ++++ www/doc-kit.config.mjs | 1 + 6 files changed, 81 insertions(+), 22 deletions(-) create mode 100644 .changeset/crosslinks.md create mode 100644 packages/react/src/html/ui/components/Layout/index.module.css diff --git a/.changeset/crosslinks.md b/.changeset/crosslinks.md new file mode 100644 index 00000000..3b85ef02 --- /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` \ No newline at end of file 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..3980559c 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,57 @@ 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.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 && ( + + )} +
+
+
- -
-
-
- -); +
+