From bc4fb65ad1d27130d4ec2a04fe855eab10b2f7bd Mon Sep 17 00:00:00 2001 From: Kamil Majkrzak Date: Mon, 25 May 2026 18:11:09 +0200 Subject: [PATCH 1/5] Docs design-system MVP --- astro.config.mjs | 6 + package.json | 5 +- pnpm-lock.yaml | 395 +++++++++++++- src/design-system/README.md | 228 ++++++++ .../docs-shell/DocsBreadcrumbs.astro | 39 ++ .../docs-shell/DocsContentLayout.astro | 198 +++++++ src/design-system/docs-shell/DocsHead.astro | 135 +++++ src/design-system/docs-shell/DocsHeader.astro | 344 ++++++++++++ src/design-system/docs-shell/DocsLayout.astro | 115 ++++ .../docs-shell/DocsSidebar.astro | 51 ++ .../docs-shell/DocsSidebarNav.astro | 94 ++++ src/design-system/docs-shell/DocsToc.astro | 85 +++ src/design-system/theme.css | 512 ++++++++++++++++++ src/design-system/tokens.css | 162 ++++++ src/design-system/ui/Badge.astro | 26 + src/design-system/ui/Button.astro | 39 ++ src/design-system/ui/Callout.astro | 67 +++ src/design-system/ui/Card.astro | 45 ++ src/design-system/ui/CodeBlock.astro | 101 ++++ src/pages/docs.mdx | 2 +- src/pages/docs/ui-mvp.astro | 200 +++++++ src/pages/ui-update-sample.mdx | 2 +- 22 files changed, 2838 insertions(+), 13 deletions(-) create mode 100644 src/design-system/README.md create mode 100644 src/design-system/docs-shell/DocsBreadcrumbs.astro create mode 100644 src/design-system/docs-shell/DocsContentLayout.astro create mode 100644 src/design-system/docs-shell/DocsHead.astro create mode 100644 src/design-system/docs-shell/DocsHeader.astro create mode 100644 src/design-system/docs-shell/DocsLayout.astro create mode 100644 src/design-system/docs-shell/DocsSidebar.astro create mode 100644 src/design-system/docs-shell/DocsSidebarNav.astro create mode 100644 src/design-system/docs-shell/DocsToc.astro create mode 100644 src/design-system/theme.css create mode 100644 src/design-system/tokens.css create mode 100644 src/design-system/ui/Badge.astro create mode 100644 src/design-system/ui/Button.astro create mode 100644 src/design-system/ui/Callout.astro create mode 100644 src/design-system/ui/Card.astro create mode 100644 src/design-system/ui/CodeBlock.astro create mode 100644 src/pages/docs/ui-mvp.astro diff --git a/astro.config.mjs b/astro.config.mjs index 541c7c43be..3a8ceba87f 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -2,6 +2,7 @@ import remarkDirective from 'remark-directive'; import remarkHeading from 'remark-heading-id'; import { defineConfig } from 'astro/config'; import mdx from '@astrojs/mdx'; +import tailwindcss from '@tailwindcss/vite'; import { attributeMarkdown, wrapTables } from '/src/themes/octopus/utilities/custom-markdown.mjs'; import llmMdEmitter from './src/integrations/llm-md-emitter.ts'; @@ -12,6 +13,11 @@ export default defineConfig({ mdx(), llmMdEmitter() ], + // Tailwind v4 only lands on pages that import the design-system entry + // (src/design-system/theme.css), so the live site stays untouched. + vite: { + plugins: [tailwindcss()] + }, markdown: { shikiConfig: { theme: 'light-plus' diff --git a/package.json b/package.json index 80a61b7ca8..b3a5d5de83 100644 --- a/package.json +++ b/package.json @@ -43,13 +43,16 @@ "devDependencies": { "@playwright/test": "^1.59.1", "@pnpm/exe": "^11.0.9", + "@tailwindcss/typography": "^0.5.19", + "@tailwindcss/vite": "^4.3.0", "cspell": "^10.0.0", "csv-parse": "^6.2.1", "linkinator": "7.0.0", "npm-run-all": "^4.1.5", "onchange": "^7.1.0", "prettier": "^3.8.3", - "prettier-plugin-astro": "^0.14.1" + "prettier-plugin-astro": "^0.14.1", + "tailwindcss": "^4.3.0" }, "pnpm": { "overrides": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 939299a054..a022fedb80 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,10 +20,10 @@ importers: dependencies: '@astrojs/mdx': specifier: ^5.0.4 - version: 5.0.4(astro@6.3.1(@types/node@24.10.1)(rollup@4.60.3)(yaml@2.8.4)) + version: 5.0.4(astro@6.3.1(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.60.3)(yaml@2.8.4)) astro: specifier: ^6.3.1 - version: 6.3.1(@types/node@24.10.1)(rollup@4.60.3)(yaml@2.8.4) + version: 6.3.1(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.60.3)(yaml@2.8.4) astro-accelerator-utils: specifier: ^0.3.84 version: 0.3.84 @@ -61,6 +61,12 @@ importers: '@pnpm/exe': specifier: ^11.0.9 version: 11.0.9 + '@tailwindcss/typography': + specifier: ^0.5.19 + version: 0.5.19(tailwindcss@4.3.0) + '@tailwindcss/vite': + specifier: ^4.3.0 + version: 4.3.0(vite@7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4)) cspell: specifier: ^10.0.0 version: 10.0.0 @@ -82,6 +88,9 @@ importers: prettier-plugin-astro: specifier: ^0.14.1 version: 0.14.1 + tailwindcss: + specifier: ^4.3.0 + version: 4.3.0 packages: @@ -680,9 +689,22 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@mdx-js/mdx@3.1.1': resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} @@ -959,6 +981,101 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@tailwindcss/node@4.3.0': + resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} + + '@tailwindcss/oxide-android-arm64@4.3.0': + resolution: {integrity: sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.0': + resolution: {integrity: sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.0': + resolution: {integrity: sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.0': + resolution: {integrity: sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + resolution: {integrity: sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + resolution: {integrity: sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + resolution: {integrity: sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + resolution: {integrity: sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + resolution: {integrity: sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + resolution: {integrity: sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + resolution: {integrity: sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + resolution: {integrity: sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.0': + resolution: {integrity: sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==} + engines: {node: '>= 20'} + + '@tailwindcss/typography@0.5.19': + resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} + peerDependencies: + tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' + + '@tailwindcss/vite@4.3.0': + resolution: {integrity: sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} @@ -1272,6 +1389,11 @@ packages: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + csso@5.0.5: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} @@ -1369,6 +1491,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enhanced-resolve@5.22.0: + resolution: {integrity: sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==} + engines: {node: '>=10.13.0'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -1882,6 +2008,10 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + js-yaml@3.14.2: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} hasBin: true @@ -1907,6 +2037,76 @@ packages: leac@0.7.0: resolution: {integrity: sha512-qMrZeyEekgdRQ9o6a4NAB2EQZrv827GJdn1vnapwSJ90hWRB4TzUSunvacPkxQ2TnNqHNI1/zSt0hlo0crG8Jw==} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + linkinator@7.0.0: resolution: {integrity: sha512-81sjQATza2eVL5Bqk96QrdVnYYI6fxWSrOHIC3/oWM6qG+5ARqwAVVwkrqSZ6RawsJcBRqOmOm4pkkj3r6Nrow==} engines: {node: '>=20'} @@ -2318,6 +2518,10 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} + postcss-selector-parser@6.0.10: + resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} + engines: {node: '>=4'} + postcss@8.5.14: resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} @@ -2661,6 +2865,13 @@ packages: engines: {node: '>=16'} hasBin: true + tailwindcss@4.3.0: + resolution: {integrity: sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} @@ -2832,6 +3043,9 @@ packages: uploadthing: optional: true + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -3000,12 +3214,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@5.0.4(astro@6.3.1(@types/node@24.10.1)(rollup@4.60.3)(yaml@2.8.4))': + '@astrojs/mdx@5.0.4(astro@6.3.1(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.60.3)(yaml@2.8.4))': dependencies: '@astrojs/markdown-remark': 7.1.1 '@mdx-js/mdx': 3.1.1 acorn: 8.16.0 - astro: 6.3.1(@types/node@24.10.1)(rollup@4.60.3)(yaml@2.8.4) + astro: 6.3.1(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.60.3)(yaml@2.8.4) es-module-lexer: 2.1.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -3474,8 +3688,25 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + '@mdx-js/mdx@3.1.1': dependencies: '@types/estree': 1.0.9 @@ -3713,6 +3944,79 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} + '@tailwindcss/node@4.3.0': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.22.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.0 + + '@tailwindcss/oxide-android-arm64@4.3.0': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.0': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.0': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.0': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.0': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.0': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.0': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.0': + optional: true + + '@tailwindcss/oxide@4.3.0': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-arm64': 4.3.0 + '@tailwindcss/oxide-darwin-x64': 4.3.0 + '@tailwindcss/oxide-freebsd-x64': 4.3.0 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.0 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.0 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.0 + '@tailwindcss/oxide-linux-x64-musl': 4.3.0 + '@tailwindcss/oxide-wasm32-wasi': 4.3.0 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.0 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.0 + + '@tailwindcss/typography@0.5.19(tailwindcss@4.3.0)': + dependencies: + postcss-selector-parser: 6.0.10 + tailwindcss: 4.3.0 + + '@tailwindcss/vite@4.3.0(vite@7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4))': + dependencies: + '@tailwindcss/node': 4.3.0 + '@tailwindcss/oxide': 4.3.0 + tailwindcss: 4.3.0 + vite: 7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4) + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 @@ -3810,7 +4114,7 @@ snapshots: astro-accelerator-utils@0.3.84: {} - astro@6.3.1(@types/node@24.10.1)(rollup@4.60.3)(yaml@2.8.4): + astro@6.3.1(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.60.3)(yaml@2.8.4): dependencies: '@astrojs/compiler': 4.0.0 '@astrojs/internal-helpers': 0.9.0 @@ -3862,8 +4166,8 @@ snapshots: unist-util-visit: 5.1.0 unstorage: 1.17.5 vfile: 6.0.3 - vite: 7.3.3(@types/node@24.10.1)(yaml@2.8.4) - vitefu: 1.1.3(vite@7.3.3(@types/node@24.10.1)(yaml@2.8.4)) + vite: 7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4) + vitefu: 1.1.3(vite@7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4)) xxhash-wasm: 1.1.0 yargs-parser: 22.0.0 zod: 4.4.3 @@ -4147,6 +4451,8 @@ snapshots: css-what@6.2.2: {} + cssesc@3.0.0: {} + csso@5.0.5: dependencies: css-tree: 2.2.1 @@ -4241,6 +4547,11 @@ snapshots: emoji-regex@9.2.2: {} + enhanced-resolve@5.22.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + entities@4.5.0: {} entities@6.0.1: {} @@ -4929,6 +5240,8 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jiti@2.7.0: {} + js-yaml@3.14.2: dependencies: argparse: 1.0.10 @@ -4948,6 +5261,55 @@ snapshots: leac@0.7.0: {} + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + linkinator@7.0.0: dependencies: chalk: 5.6.2 @@ -5650,6 +6012,11 @@ snapshots: possible-typed-array-names@1.1.0: {} + postcss-selector-parser@6.0.10: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + postcss@8.5.14: dependencies: nanoid: 3.3.12 @@ -6173,6 +6540,10 @@ snapshots: picocolors: 1.1.1 sax: 1.6.0 + tailwindcss@4.3.0: {} + + tapable@2.3.3: {} + tiny-inflate@1.0.3: {} tinyclip@0.1.12: {} @@ -6329,6 +6700,8 @@ snapshots: ofetch: 1.5.1 ufo: 1.6.4 + util-deprecate@1.0.2: {} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -6349,7 +6722,7 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite@7.3.3(@types/node@24.10.1)(yaml@2.8.4): + vite@7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4): dependencies: esbuild: 0.28.0 fdir: 6.5.0(picomatch@4.0.4) @@ -6360,11 +6733,13 @@ snapshots: optionalDependencies: '@types/node': 24.10.1 fsevents: 2.3.3 + jiti: 2.7.0 + lightningcss: 1.32.0 yaml: 2.8.4 - vitefu@1.1.3(vite@7.3.3(@types/node@24.10.1)(yaml@2.8.4)): + vitefu@1.1.3(vite@7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4)): optionalDependencies: - vite: 7.3.3(@types/node@24.10.1)(yaml@2.8.4) + vite: 7.3.3(@types/node@24.10.1)(jiti@2.7.0)(lightningcss@1.32.0)(yaml@2.8.4) vscode-languageserver-textdocument@1.0.12: {} diff --git a/src/design-system/README.md b/src/design-system/README.md new file mode 100644 index 0000000000..eb251959ed --- /dev/null +++ b/src/design-system/README.md @@ -0,0 +1,228 @@ +# Octopus Design System (portable module) + +A self-contained, framework-free design system for Octopus Astro sites. It exists so the +docs site and the other (drifted) microsites can share **one** visual language instead of +each maintaining its own CSS. Everything here is plain Astro + CSS custom properties + +Tailwind v4 utilities - **no React/Vue/Svelte, no client framework runtime** - which keeps +SEO and Core Web Vitals intact on statically generated pages. + +> Status: MVP. Proven in this repo on `/docs/ui-mvp`, which is the first consumer of this +> module. Adopt it elsewhere by copying this one folder and wiring two things. + +--- + +## 1. Anatomy + +``` +src/design-system/ +├── README.md ← this file +├── tokens.css ← brand + semantic CSS variables (THE customization surface) +├── theme.css ← Tailwind v4 entry: imports tokens, maps them into the @theme, +│ tunes the typography plugin. Import this once per page. +├── ui/ ← universal primitives (any Octopus site: docs, marketing, app) +│ ├── Button.astro +│ ├── Badge.astro +│ ├── Card.astro +│ ├── Callout.astro +│ └── CodeBlock.astro ← code surface + filename bar + vanilla copy button +└── docs-shell/ ← documentation-site chrome (only docs-style sites need this) + ├── DocsLayout.astro ← page shell: , header, sidebar, article, toc, footer + ├── DocsHeader.astro ← top bar: real OctopusLogo, search w/ results dropdown, + │ theme toggle, trial CTA + ├── DocsSidebar.astro ← left section nav + ├── DocsToc.astro ← right "on this page" nav w/ scroll-spy + └── DocsBreadcrumbs.astro ← RDFa BreadcrumbList breadcrumbs +``` + +**Two tiers, adopt independently:** +- `tokens.css` + `theme.css` + `ui/` - the universal core. Any Octopus Astro site can use it. +- `docs-shell/` - opinionated documentation chrome. Take it for docs sites; skip it for + marketing/app sites and build their own shells on top of the core. + +--- + +## 2. The single customization surface: `tokens.css` + +`tokens.css` is the **only** file a site is expected to edit. It defines two layers: + +1. **Brand primitives** - the literal Octopus palette (`--octo-blue`, `--octo-green`, the + navy scale) and font stacks. These are the brand source of truth, mirrored from + `public/docs/css/vars.css`. +2. **Semantic tokens** (shadcn shape) - `--background`, `--foreground`, `--primary`, + `--accent`, `--muted`, `--border`, `--ring`, callout intents, surfaces, elevation, etc., + defined for light (`:root`) and dark (`[data-theme='dark']`). + +Components and `theme.css` reference **only the semantic tokens**, never raw hex. So: +- Re-skinning a site = edit `tokens.css`, nothing else. +- Because every microsite is the *same* Octopus brand, `tokens.css` ports **1:1 unchanged** - + that is the whole point: copy it verbatim and every site converges on one look. Only fork + it if a site genuinely needs to diverge. + +Dark mode is driven by the `[data-theme='dark']` attribute on `` (matches the existing +Octopus site switch), not a Tailwind `dark:` class. + +--- + +## 3. Adopting it in another repo + +**Prerequisites:** Astro 5+ (built/tested on Astro 6.3) using Vite, and pnpm. + +### Step 1 - install dependencies + +```bash +pnpm add -D tailwindcss@^4 @tailwindcss/vite@^4 @tailwindcss/typography@^0.5 +``` + +### Step 2 - wire the Tailwind v4 Vite plugin + +Tailwind v4 is added as a **Vite plugin**, not an Astro integration. In `astro.config.mjs`: + +```js +import tailwindcss from '@tailwindcss/vite'; + +export default defineConfig({ + // ...existing integrations stay as-is... + vite: { + plugins: [tailwindcss()], + }, +}); +``` + +This is global to the build, but Tailwind only emits CSS for pages that actually **import +`theme.css`** - so it does not leak onto pages that don't opt in. + +### Step 3 - copy the module + +Copy `src/design-system/` into the target repo's `src/`. Keep the folder intact so the +relative imports inside it keep working (`theme.css` → `./tokens.css`, `docs-shell` files → +each other). + +### Step 4 - satisfy the `docs-shell` external dependencies (docs sites only) + +`docs-shell` deliberately reuses two existing shared Octopus assets rather than reinventing +them. If you adopt `docs-shell`, the target repo must provide: + +| Dependency | Used by | Path in this repo | Notes | +|---|---|---|---| +| `OctopusLogo.astro` | `DocsHeader.astro` | `public/docs/img/OctopusLogo.astro` | The genuine wordmark+glyph. Import path is `../../../public/docs/img/OctopusLogo.astro` - adjust if your asset lives elsewhere. | +| Shared `Footer.astro` | `DocsLayout.astro` | `src/components/Footer.astro` | Imported as `../../components/Footer.astro`. Swap for the site's own footer if needed. | +| `footer-bundle.css` | `DocsLayout.astro` `` | `public/docs/css/footer-bundle.css` | Linked by absolute URL `/docs/css/footer-bundle.css`. | + +The `ui/` core has **no** external dependencies. + +### Step 5 - use it + +```astro +--- +import DocsLayout from '../design-system/docs-shell/DocsLayout.astro'; +import Callout from '../design-system/ui/Callout.astro'; +import Card from '../design-system/ui/Card.astro'; +import Button from '../design-system/ui/Button.astro'; +import Badge from '../design-system/ui/Badge.astro'; +import CodeBlock from '../design-system/ui/CodeBlock.astro'; +--- + + Body text… + + +``` + +For a non-docs site, import `theme.css` once in your own layout's frontmatter and use the +`ui/` primitives: + +```astro +--- +import '../design-system/theme.css'; +import Button from '../design-system/ui/Button.astro'; +--- +``` + +> Tip: add an alias (e.g. `@ds/*` → `src/design-system/*`) in `tsconfig.json` / +> `astro.config` to avoid `../../` import chains. Optional. + +--- + +## 3a. Finding what's what (developer experience) + +With Tailwind the styling lives **on the element, inside the component file** — there is no +semantic stylesheet like the old `main.css` to grep for `.article-nav__title`. The source of +truth is the `.astro` component, not a CSS file. To keep the DOM traceable we tag every +component's root element with a **`data-component=""`** attribute. + +Workflow to locate and fix anything: +1. Inspect the element in browser devtools. +2. Walk up to the nearest `[data-component="X"]`. +3. Open `src/design-system/**/X.astro` — the Tailwind classes you want to change are right + there on the element (the component bodies are small and readable). + +Example: a sidebar link → nearest `data-component` is `DocsSidebarNav` → edit +`docs-shell/DocsSidebarNav.astro`. The nav region itself is `DocsSidebar` (the `
@@ -116,7 +148,7 @@ const sortedTopLevel = pages class="min-w-0 flex-1 px-5 py-6 sm:px-6 lg:px-12 lg:py-14" data-component="DocsContentLayout" > -
+
@@ -171,7 +203,7 @@ const sortedTopLevel = pages

{frontmatter.title} @@ -191,7 +223,7 @@ const sortedTopLevel = pages

{frontmatter.description} diff --git a/src/design-system/docs-shell/DocsHeader.astro b/src/design-system/docs-shell/DocsHeader.astro index 3e98a47f36..7ae8865ea7 100644 --- a/src/design-system/docs-shell/DocsHeader.astro +++ b/src/design-system/docs-shell/DocsHeader.astro @@ -1,8 +1,17 @@ --- // Top navigation bar. The only JS is a tiny theme toggle (vanilla, no framework // runtime) to demonstrate dark mode - consistent with the zero-JS approach. +// Search renders the REAL site search component + engine (search.js), restyled +// via tokens in theme.css. The engine is unchanged; we only provide its markup. import OctopusLogo from '../../../public/docs/img/OctopusLogo.astro'; import Button from '../ui/Button.astro'; +import Search from '../../themes/octopus/components/Search.astro'; +import { SITE } from '@config'; + +type Props = { + lang?: string; +}; +const { lang = SITE.default.lang } = Astro.props satisfies Props; ---

- -