From b899f95cf66a740912bddc66d90d2b000e3472dd Mon Sep 17 00:00:00 2001 From: Glen Huang Date: Thu, 16 Oct 2025 21:25:43 +0800 Subject: [PATCH] docs-site: implement tabs --- pkgs/docs-site/src/app.html | 19 ++-- pkgs/docs-site/src/lib/markdown/main.css | 1 + pkgs/docs-site/src/lib/markdown/tabs.css | 50 ++++++++++ pkgs/docs-site/src/lib/markdown/vite/index.ts | 2 + .../src/lib/markdown/vite/remark-tabs.ts | 93 +++++++++++++++++++ pkgs/docs-site/src/routes/+layout.svelte | 2 +- .../src/routes/[...path]/+page.svelte | 33 ++++++- .../docs/getting-started/add-machines.md | 25 ++++- pkgs/docs-site/src/routes/global.css | 2 +- 9 files changed, 214 insertions(+), 13 deletions(-) create mode 100644 pkgs/docs-site/src/lib/markdown/tabs.css create mode 100644 pkgs/docs-site/src/lib/markdown/vite/remark-tabs.ts diff --git a/pkgs/docs-site/src/app.html b/pkgs/docs-site/src/app.html index f273cc58f..adc6da57c 100644 --- a/pkgs/docs-site/src/app.html +++ b/pkgs/docs-site/src/app.html @@ -1,11 +1,14 @@ - - - - %sveltekit.head% - - -
%sveltekit.body%
- + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ diff --git a/pkgs/docs-site/src/lib/markdown/main.css b/pkgs/docs-site/src/lib/markdown/main.css index 9241d9544..a95a26557 100644 --- a/pkgs/docs-site/src/lib/markdown/main.css +++ b/pkgs/docs-site/src/lib/markdown/main.css @@ -1,5 +1,6 @@ @import url("./shiki.css"); @import url("./admonition.css"); +@import url("./tabs.css"); code { font-family: diff --git a/pkgs/docs-site/src/lib/markdown/tabs.css b/pkgs/docs-site/src/lib/markdown/tabs.css new file mode 100644 index 000000000..6e4ed6618 --- /dev/null +++ b/pkgs/docs-site/src/lib/markdown/tabs.css @@ -0,0 +1,50 @@ +.md-tabs-bar { + display: none; + gap: 7px; + align-items: flex-end; +} +.md-tabs-tab { + padding: 8px 0; +} +.md-tabs-container { + margin: 20px 0; +} +.js { + .md-tabs-bar { + display: flex; + } + .md-tabs-container { + margin: 0; + > .md-tabs-tab { + display: none; + } + } + .md-tabs { + margin: 20px 0; + } + .md-tabs-tab { + background: #d7dadf; + padding: 8px 18px; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + cursor: pointer; + &.is-active { + background: #eff1f5; + + .md-tabs.is-singleton & { + padding: 8px 16px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + flex: 1; + border-bottom: 1px solid #d8dbe1; + } + } + } + .md-tabs-content { + display: none; + margin: 0 var(--pageMargin); + &.is-active { + display: block; + } + } +} diff --git a/pkgs/docs-site/src/lib/markdown/vite/index.ts b/pkgs/docs-site/src/lib/markdown/vite/index.ts index a9c23f2bc..76b1543a7 100644 --- a/pkgs/docs-site/src/lib/markdown/vite/index.ts +++ b/pkgs/docs-site/src/lib/markdown/vite/index.ts @@ -17,6 +17,7 @@ import rehypeTocSlug from "./rehype-toc-slug"; import transformerLineNumbers from "./shiki-transformer-line-numbers"; import remarkParse from "./remark-parse"; import remarkAdmonition from "./remark-admonition"; +import remarkTabs from "./remark-tabs"; import rehypeWrapHeadings from "./rehype-wrap-headings"; import remarkLinkMigration from "./link-migration"; @@ -44,6 +45,7 @@ export default function ({ .use(remarkGfm) .use(remarkDirective) .use(remarkAdmonition) + .use(remarkTabs) .use(remarkRehype) .use(rehypeTocSlug, { tocMaxDepth, diff --git a/pkgs/docs-site/src/lib/markdown/vite/remark-tabs.ts b/pkgs/docs-site/src/lib/markdown/vite/remark-tabs.ts new file mode 100644 index 000000000..8893a622b --- /dev/null +++ b/pkgs/docs-site/src/lib/markdown/vite/remark-tabs.ts @@ -0,0 +1,93 @@ +import { visit } from "unist-util-visit"; +import type { Paragraph, Root, Text } from "mdast"; + +export default function remarkTabs() { + return (tree: Root) => { + visit(tree, (node) => { + if (node.type != "containerDirective" || node.name != "tabs") { + return; + } + + const data = (node.data ||= {}); + data.hName = "div"; + data.hProperties = { + className: "md-tabs", + }; + let tabIndex = 0; + let tabTitles: string[] = []; + for (const [i, child] of node.children.entries()) { + if (child.type != "containerDirective" || child.name != "tab") { + continue; + } + let tabTitle: string; + if (child.children?.[0].data?.directiveLabel) { + const p = child.children.shift() as Paragraph; + tabTitle = (p.children[0] as Text).value; + } else { + tabTitle = "(empty)"; + } + tabTitles.push(tabTitle); + node.children[i] = { + type: "containerDirective", + name: "", + data: { + hName: "div", + hProperties: { + className: "md-tabs-container", + }, + }, + children: [ + { + type: "paragraph", + data: { + hName: "div", + hProperties: { + className: `md-tabs-tab ${tabIndex == 0 ? "is-active" : ""}`, + }, + }, + children: [{ type: "text", value: tabTitle }], + }, + { + type: "containerDirective", + name: "", + data: { + hName: "div", + hProperties: { + className: `md-tabs-content ${tabIndex == 0 ? "is-active" : ""}`, + }, + }, + children: child.children, + }, + ], + }; + tabIndex++; + } + if (tabTitles.length === 1) { + data.hProperties.className += " is-singleton"; + } + // Add tab bar for when js is enabled + node.children = [ + { + type: "paragraph", + data: { + hName: "div", + hProperties: { + className: "md-tabs-bar", + }, + }, + children: tabTitles.map((tabTitle, tabIndex) => ({ + type: "text", + data: { + hName: "div", + hProperties: { + className: `md-tabs-tab ${tabIndex == 0 ? "is-active" : ""}`, + }, + }, + value: tabTitle, + })), + }, + ...node.children, + ]; + }); + }; +} diff --git a/pkgs/docs-site/src/routes/+layout.svelte b/pkgs/docs-site/src/routes/+layout.svelte index f099d830d..5db9e9c22 100644 --- a/pkgs/docs-site/src/routes/+layout.svelte +++ b/pkgs/docs-site/src/routes/+layout.svelte @@ -111,7 +111,7 @@ display: flex; justify-content: space-between; align-items: center; - padding: 0 var(--pagePadding); + padding: 0 var(--pageMargin); color: var(--fgInvertedColor); background: var(--bgInvertedColor); } diff --git a/pkgs/docs-site/src/routes/[...path]/+page.svelte b/pkgs/docs-site/src/routes/[...path]/+page.svelte index 84bb0d1bb..1d9299540 100644 --- a/pkgs/docs-site/src/routes/[...path]/+page.svelte +++ b/pkgs/docs-site/src/routes/[...path]/+page.svelte @@ -1,6 +1,7 @@