From 72d612537a64d32cfcbed058b869baef0ec1aebc Mon Sep 17 00:00:00 2001
From: aeei <18022843+aeei@users.noreply.github.com>
Date: Tue, 21 Jul 2026 15:30:13 +0900
Subject: [PATCH 1/5] fix(theme): restore Mermaid prose spacing
---
README.md | 2 +-
packages/docusaurus-theme/package.json | 4 ++--
packages/docusaurus-theme/src/package-contract.test.ts | 4 ++--
packages/docusaurus-theme/src/theme/base.scss | 1 +
.../docusaurus-theme/src/theme/mermaid-contract.test.ts | 6 ++++++
5 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 2e3317dc6..f32c7ec23 100644
--- a/README.md
+++ b/README.md
@@ -172,7 +172,7 @@ Requirements:
Consumers then install a pinned release:
```bash
-npm install @aeei/docusaurus-theme@0.1.5
+npm install @aeei/docusaurus-theme@0.1.6
```
This repository does not publish automatically from an unapproved working tree.
diff --git a/packages/docusaurus-theme/package.json b/packages/docusaurus-theme/package.json
index c23eb9e88..48b1ff237 100644
--- a/packages/docusaurus-theme/package.json
+++ b/packages/docusaurus-theme/package.json
@@ -1,6 +1,6 @@
{
"name": "@aeei/docusaurus-theme",
- "version": "0.1.5",
+ "version": "0.1.6",
"description": "A shadcn Base Nova theme for Docusaurus docs.",
"license": "MIT",
"keywords": [
@@ -16,7 +16,7 @@
},
"repository": {
"type": "git",
- "url": "https://github.com/aeei/docusaurus-theme.git",
+ "url": "git+https://github.com/aeei/docusaurus-theme.git",
"directory": "packages/docusaurus-theme"
},
"bugs": {
diff --git a/packages/docusaurus-theme/src/package-contract.test.ts b/packages/docusaurus-theme/src/package-contract.test.ts
index 6746ccdd9..d42420220 100644
--- a/packages/docusaurus-theme/src/package-contract.test.ts
+++ b/packages/docusaurus-theme/src/package-contract.test.ts
@@ -19,13 +19,13 @@ it("uses the public docs-only package identity and metadata", () => {
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
expect(packageJson.name).toBe("@aeei/docusaurus-theme");
- expect(packageJson.version).toBe("0.1.5");
+ expect(packageJson.version).toBe("0.1.6");
expect(packageJson.description).toBe(
"A shadcn Base Nova theme for Docusaurus docs."
);
expect(packageJson.repository).toEqual({
type: "git",
- url: "https://github.com/aeei/docusaurus-theme.git",
+ url: "git+https://github.com/aeei/docusaurus-theme.git",
directory: "packages/docusaurus-theme",
});
expect(packageJson.bugs).toEqual({
diff --git a/packages/docusaurus-theme/src/theme/base.scss b/packages/docusaurus-theme/src/theme/base.scss
index 9dd975561..f08fa69df 100644
--- a/packages/docusaurus-theme/src/theme/base.scss
+++ b/packages/docusaurus-theme/src/theme/base.scss
@@ -1717,6 +1717,7 @@ a[class*="skipToContent"]:focus {
}
.theme-doc-markdown .docusaurus-mermaid-container {
+ margin-block-start: var(--typeset-flow);
display: flex;
justify-content: safe center;
overflow-x: auto;
diff --git a/packages/docusaurus-theme/src/theme/mermaid-contract.test.ts b/packages/docusaurus-theme/src/theme/mermaid-contract.test.ts
index 9398376da..ac8f91d8f 100644
--- a/packages/docusaurus-theme/src/theme/mermaid-contract.test.ts
+++ b/packages/docusaurus-theme/src/theme/mermaid-contract.test.ts
@@ -23,6 +23,12 @@ describe("Mermaid ownership contract", () => {
);
});
+ it("keeps Mermaid diagrams in the article flow rhythm", () => {
+ expect(stylesheet).toMatch(
+ /\.theme-doc-markdown \.docusaurus-mermaid-container\s*\{[^}]*margin-block-start: var\(--typeset-flow\);[^}]*\}/
+ );
+ });
+
it("keeps wide actual-route diagrams readable in a horizontal scroll surface", () => {
expect(stylesheet).toMatch(
/\.docusaurus-mermaid-container\s*\{[\s\S]*justify-content: safe center;[\s\S]*overflow-x: auto;/
From c8feb071160936f46d1f9060ca711481e278ad9f Mon Sep 17 00:00:00 2001
From: aeei <18022843+aeei@users.noreply.github.com>
Date: Wed, 22 Jul 2026 00:16:08 +0900
Subject: [PATCH 2/5] fix(theme): align TOC inline code styling
---
.../docs-starter/docs/guides/markdown-gfm.md | 4 +++
.../src/theme/TOCItems/Tree.tsx | 6 +++-
packages/docusaurus-theme/src/theme/base.scss | 19 +++++------
.../docusaurus-theme/src/theme/base.test.ts | 4 ++-
.../src/theme/prose-contract.test.ts | 21 ++++++++++++
tests/theme-parity.spec.ts | 34 +++++++++++++++++++
6 files changed, 76 insertions(+), 12 deletions(-)
diff --git a/examples/docs-starter/docs/guides/markdown-gfm.md b/examples/docs-starter/docs/guides/markdown-gfm.md
index 14e976028..dec3aa272 100644
--- a/examples/docs-starter/docs/guides/markdown-gfm.md
+++ b/examples/docs-starter/docs/guides/markdown-gfm.md
@@ -10,6 +10,10 @@ This page exercises standard Markdown, GFM, and Docusaurus docs conventions.
## Table of contents depth
+### Inline code heading `provider-id`
+
+This heading verifies that table-of-contents code uses the canonical inline code surface.
+
### Link targets
Jump to [paragraph flow](#paragraph-flow-and-emphasis), [lists](#lists-and-tasks), [tables](#tables), or [details](#details-and-admonitions).
diff --git a/packages/docusaurus-theme/src/theme/TOCItems/Tree.tsx b/packages/docusaurus-theme/src/theme/TOCItems/Tree.tsx
index 36e56dbd8..96d1417dc 100644
--- a/packages/docusaurus-theme/src/theme/TOCItems/Tree.tsx
+++ b/packages/docusaurus-theme/src/theme/TOCItems/Tree.tsx
@@ -13,7 +13,11 @@ function HeadingLabel({ html }: { html: string }): React.JSX.Element {
const code = part.match(codeContentPattern);
if (code) {
return (
-
+
);
}
diff --git a/packages/docusaurus-theme/src/theme/base.scss b/packages/docusaurus-theme/src/theme/base.scss
index f08fa69df..bf4125ffe 100644
--- a/packages/docusaurus-theme/src/theme/base.scss
+++ b/packages/docusaurus-theme/src/theme/base.scss
@@ -69,6 +69,8 @@
--theme-leading-sm: 1.25rem;
--theme-text-xs: 0.75rem;
--theme-leading-xs: 1rem;
+ --theme-prose-body-size: 0.9375rem;
+ --theme-prose-leading: 1.75;
--theme-backdrop-blur: 12px;
}
@@ -508,9 +510,9 @@ a[class*="skipToContent"]:focus {
--typeset-font-body: inherit;
--typeset-font-heading: var(--ifm-heading-font-family);
--typeset-font-mono: var(--ifm-font-family-monospace);
- --typeset-size: 0.9375rem;
+ --typeset-size: var(--theme-prose-body-size);
--typeset-body-size: var(--typeset-size);
- --typeset-leading: 1.75;
+ --typeset-leading: var(--theme-prose-leading);
--typeset-flow: 1.25em;
--typeset-muted: var(--muted-foreground);
--typeset-rule: var(--border);
@@ -1147,9 +1149,11 @@ a[class*="skipToContent"]:focus {
border-radius: min(calc(var(--radius) * 0.6), 0.35em);
background-color: var(--muted);
color: inherit;
- font-family: var(--typeset-font-mono);
- font-size: calc(var(--typeset-body-size) * 0.85);
- line-height: var(--typeset-leading);
+ font-family: var(--typeset-font-mono, var(--ifm-font-family-monospace));
+ font-size: calc(
+ var(--typeset-body-size, var(--theme-prose-body-size)) * 0.85
+ );
+ line-height: var(--typeset-leading, var(--theme-prose-leading));
padding: 0.125em 0.3em;
}
@@ -1778,11 +1782,6 @@ a[class*="skipToContent"]:focus {
transition: color 150ms ease;
}
-.table-of-contents__link code {
- font-size: inherit;
- line-height: inherit;
-}
-
.table-of-contents__link[data-depth="3"] {
padding-left: calc(var(--spacing) * 4);
}
diff --git a/packages/docusaurus-theme/src/theme/base.test.ts b/packages/docusaurus-theme/src/theme/base.test.ts
index ba1aedd86..f0059d085 100644
--- a/packages/docusaurus-theme/src/theme/base.test.ts
+++ b/packages/docusaurus-theme/src/theme/base.test.ts
@@ -22,7 +22,9 @@ it("leaves component focus visuals to official primitives", () => {
});
it("keeps article prose size stable across responsive widths", () => {
- expect(stylesheet).toContain("--typeset-size: 0.9375rem;");
+ expect(stylesheet).toContain("--theme-prose-body-size: 0.9375rem;");
+ expect(stylesheet).toContain("--theme-prose-leading: 1.75;");
+ expect(stylesheet).toContain("--typeset-size: var(--theme-prose-body-size);");
expect(stylesheet).toContain("--typeset-flow: 1.25em;");
expect(stylesheet).toContain("--typeset-body-size: var(--typeset-size);");
expect(stylesheet).toContain("font-size: var(--typeset-body-size);");
diff --git a/packages/docusaurus-theme/src/theme/prose-contract.test.ts b/packages/docusaurus-theme/src/theme/prose-contract.test.ts
index df4495f9d..665bdae1a 100644
--- a/packages/docusaurus-theme/src/theme/prose-contract.test.ts
+++ b/packages/docusaurus-theme/src/theme/prose-contract.test.ts
@@ -49,6 +49,27 @@ describe("prose ownership contract", () => {
expect(stylesheet).not.toContain(":where(:not(pre) > code)");
});
+ it("reuses canonical inline code styling in table-of-contents labels", () => {
+ const tocTree = fs.readFileSync(
+ path.join(__dirname, "TOCItems/Tree.tsx"),
+ "utf8"
+ );
+
+ expect(tocTree).toContain('className="theme-code-inline"');
+ expect(stylesheet).not.toContain(".table-of-contents__link code {");
+ expect(stylesheet).toContain("--theme-prose-body-size: 0.9375rem;");
+ expect(stylesheet).toContain("--theme-prose-leading: 1.75;");
+ expect(stylesheet).toContain(
+ "var(--typeset-font-mono, var(--ifm-font-family-monospace))"
+ );
+ expect(stylesheet).toContain(
+ "var(--typeset-body-size, var(--theme-prose-body-size))"
+ );
+ expect(stylesheet).toContain(
+ "var(--typeset-leading, var(--theme-prose-leading))"
+ );
+ });
+
it("keeps heading hash links on the official inherit contract", () => {
expect(canonicalStylesheet).toContain(
canonicalize(`${localBoundary}:where(:is(h1, h2, h3, h4, h5, h6) :is(a))`)
diff --git a/tests/theme-parity.spec.ts b/tests/theme-parity.spec.ts
index 6dfd82cd6..c28f38d26 100644
--- a/tests/theme-parity.spec.ts
+++ b/tests/theme-parity.spec.ts
@@ -804,6 +804,40 @@ test("inline code keeps one component-owned surface inside Details", async ({
}
});
+test("table-of-contents code reuses the canonical inline code surface", async ({
+ page,
+}) => {
+ await page.setViewportSize({ width: 1440, height: 900 });
+ await page.goto(markdownRoute);
+
+ const metrics = await page.evaluate(() => {
+ const content = Array.from(
+ document.querySelectorAll(".theme-doc-markdown h3 code")
+ ).find((element) => element.textContent === "provider-id");
+ const toc = Array.from(
+ document.querySelectorAll(".table-of-contents__link code")
+ ).find((element) => element.textContent === "provider-id");
+ const read = (element?: Element) => {
+ if (!element) return null;
+ const style = getComputedStyle(element);
+ return {
+ className: element.className,
+ fontFamily: style.fontFamily,
+ fontSize: style.fontSize,
+ lineHeight: style.lineHeight,
+ padding: style.padding,
+ borderRadius: style.borderRadius,
+ backgroundColor: style.backgroundColor,
+ };
+ };
+ return { content: read(content), toc: read(toc) };
+ });
+
+ expect(metrics.content).not.toBeNull();
+ expect(metrics.toc).toEqual(metrics.content);
+ expect(metrics.toc?.className).toContain("theme-code-inline");
+});
+
test("CodeBlock matches the official shadcn docs surface", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 900 });
await page.goto(markdownRoute);
From 153283b70f4f65f2a435a5b480b0877756a0805b Mon Sep 17 00:00:00 2001
From: aeei <18022843+aeei@users.noreply.github.com>
Date: Wed, 22 Jul 2026 00:16:08 +0900
Subject: [PATCH 3/5] fix(theme): filter doc metadata from navbar links
---
.../src/theme/Navbar/Content/index.tsx | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx b/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx
index 3903a992f..df7178074 100644
--- a/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx
+++ b/packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx
@@ -74,8 +74,12 @@ function NavbarNavigationMenuDocItem({
}: {
item: NavigationItemConfig;
}): ReactNode {
- const { activeDoc } = useActiveDocContext(item.docsPluginId);
- const doc = useLayoutDoc(item.docId!, item.docsPluginId);
+ const { docId, docsPluginId, label, ...navLinkProps } = item;
+ delete navLinkProps.type;
+ delete navLinkProps.items;
+
+ const { activeDoc } = useActiveDocContext(docsPluginId);
+ const doc = useLayoutDoc(docId!, docsPluginId);
const pageActive = activeDoc?.path === doc?.path;
if (doc === null || (doc.unlisted && !pageActive)) return null;
@@ -86,10 +90,10 @@ function NavbarNavigationMenuDocItem({
className={navigationMenuTriggerStyle()}
render={
pageActive ||
(!!activeDoc?.sidebar && activeDoc.sidebar === doc.sidebar)
From 68b8c14cfc11eae594d7c0571a1307d829b09aba Mon Sep 17 00:00:00 2001
From: aeei <18022843+aeei@users.noreply.github.com>
Date: Wed, 22 Jul 2026 00:16:09 +0900
Subject: [PATCH 4/5] chore(theme): release 0.1.7
---
README.md | 2 +-
packages/docusaurus-theme/package.json | 2 +-
packages/docusaurus-theme/src/package-contract.test.ts | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index f32c7ec23..fb5b3edbf 100644
--- a/README.md
+++ b/README.md
@@ -172,7 +172,7 @@ Requirements:
Consumers then install a pinned release:
```bash
-npm install @aeei/docusaurus-theme@0.1.6
+npm install @aeei/docusaurus-theme@0.1.7
```
This repository does not publish automatically from an unapproved working tree.
diff --git a/packages/docusaurus-theme/package.json b/packages/docusaurus-theme/package.json
index 48b1ff237..dea1d58cc 100644
--- a/packages/docusaurus-theme/package.json
+++ b/packages/docusaurus-theme/package.json
@@ -1,6 +1,6 @@
{
"name": "@aeei/docusaurus-theme",
- "version": "0.1.6",
+ "version": "0.1.7",
"description": "A shadcn Base Nova theme for Docusaurus docs.",
"license": "MIT",
"keywords": [
diff --git a/packages/docusaurus-theme/src/package-contract.test.ts b/packages/docusaurus-theme/src/package-contract.test.ts
index d42420220..3326f2899 100644
--- a/packages/docusaurus-theme/src/package-contract.test.ts
+++ b/packages/docusaurus-theme/src/package-contract.test.ts
@@ -19,7 +19,7 @@ it("uses the public docs-only package identity and metadata", () => {
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));
expect(packageJson.name).toBe("@aeei/docusaurus-theme");
- expect(packageJson.version).toBe("0.1.6");
+ expect(packageJson.version).toBe("0.1.7");
expect(packageJson.description).toBe(
"A shadcn Base Nova theme for Docusaurus docs."
);
From a6d0afbee13a50069a3cf1267e34a3b966cb789c Mon Sep 17 00:00:00 2001
From: aeei <18022843+aeei@users.noreply.github.com>
Date: Wed, 22 Jul 2026 01:05:50 +0900
Subject: [PATCH 5/5] test(theme): align audits with sticky sidebar
---
scripts/audit-critical-ui-relations.cjs | 10 ++++------
scripts/audit-docs-starter.cjs | 25 +++++++++++++------------
2 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/scripts/audit-critical-ui-relations.cjs b/scripts/audit-critical-ui-relations.cjs
index 70ddec5da..25ba001bf 100644
--- a/scripts/audit-critical-ui-relations.cjs
+++ b/scripts/audit-critical-ui-relations.cjs
@@ -193,9 +193,7 @@ async function openPage(browser, width, route = "showcase/mdx-playground") {
backgroundColor: navbarBlur.backgroundColor,
},
toc: {
- headerOutsideScroll: Boolean(
- tocHeader && tocScroll && !tocScroll.contains(tocHeader)
- ),
+ headerAbsent: !tocHeader,
scrollFade: fadeActive(tocScroll),
},
};
@@ -203,7 +201,7 @@ async function openPage(browser, width, route = "showcase/mdx-playground") {
await page.evaluate(() => scrollTo(0, document.documentElement.scrollHeight));
await page.waitForTimeout(50);
const sidebarFooterBoundary = await page.evaluate(() => {
- const sidebar = document.querySelector(".theme-doc-sidebar-container");
+ const sidebar = document.querySelector(".theme-doc-sidebar-desktop");
const sidebarFooter = sidebar?.querySelector(
'[data-slot="sidebar-footer"]'
);
@@ -335,10 +333,10 @@ async function openPage(browser, width, route = "showcase/mdx-playground") {
);
expect(
desktopSurface.sidebarScrollFade === true &&
- desktopSurface.toc.headerOutsideScroll === true &&
+ desktopSurface.toc.headerAbsent === true &&
desktopSurface.toc.scrollFade === true &&
mobileSurface.sidebarScrollFade === true,
- "LNB and TOC scroll viewports must use scroll-fade while the TOC header remains fixed",
+ "LNB and TOC scroll viewports must use scroll-fade without restoring the removed TOC header",
{ desktopSurface, mobileSurface }
);
expect(
diff --git a/scripts/audit-docs-starter.cjs b/scripts/audit-docs-starter.cjs
index 2b90aa4f7..ed2416302 100644
--- a/scripts/audit-docs-starter.cjs
+++ b/scripts/audit-docs-starter.cjs
@@ -155,7 +155,7 @@ async function auditRoute(page, viewport, theme, route) {
});
const desktopSidebar = document.querySelector(
- '[data-slot="sidebar-container"]'
+ ".theme-doc-sidebar-desktop"
);
const mobileTrigger = document.querySelector(
"[data-mobile-navigation-trigger]"
@@ -163,7 +163,7 @@ async function auditRoute(page, viewport, theme, route) {
const responsiveFailure =
viewportName === "desktop"
? !desktopSidebar ||
- getComputedStyle(desktopSidebar).position !== "fixed" ||
+ getComputedStyle(desktopSidebar).position !== "sticky" ||
mobileTrigger?.getBoundingClientRect().width
: !!desktopSidebar?.getBoundingClientRect().width ||
!mobileTrigger?.getBoundingClientRect().width;
@@ -252,20 +252,21 @@ async function auditDesktopInteractions(page, theme) {
window.scrollTo(0, document.documentElement.scrollHeight)
);
await page.waitForTimeout(100);
- const sidebarContainer = await visible(
- page,
- '[data-slot="sidebar-container"]'
- );
- const sidebarRect = await sidebarContainer.boundingBox();
+ const desktopSidebar = await visible(page, ".theme-doc-sidebar-desktop");
+ const sidebarRect = await desktopSidebar.boundingBox();
const sidebarFooter = await visible(page, '[data-slot="sidebar-footer"]');
- const footerRect = await sidebarFooter.boundingBox();
+ const sidebarFooterRect = await sidebarFooter.boundingBox();
+ const pageFooter = await visible(page, ".theme-layout-footer");
+ const pageFooterRect = await pageFooter.boundingBox();
if (
!sidebarRect ||
- !footerRect ||
- sidebarRect.y < 40 ||
- footerRect.y + footerRect.height > 901
+ !sidebarFooterRect ||
+ !pageFooterRect ||
+ sidebarRect.y < -1 ||
+ sidebarRect.y + sidebarRect.height > pageFooterRect.y + 1 ||
+ sidebarFooterRect.y + sidebarFooterRect.height > pageFooterRect.y + 1
) {
- throw new Error("fixed Sidebar/footer scroll state failed");
+ throw new Error("sticky Sidebar/footer boundary failed");
}
const themeTrigger = page.getByRole("button", { name: /^Color theme:/ });