From c5428ccb721a2b286a9bfbe64f228551ca536f46 Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Wed, 11 Feb 2026 01:43:36 +0100 Subject: [PATCH 1/4] feat: conditional exports, numerous bug fixes and ux improvements --- .github/workflows/publish-packages.yml | 5 +- .../site/components/Common/Partners/index.tsx | 15 +++-- apps/site/layouts/layouts.module.css | 8 +-- apps/site/next.fetch.mjs | 2 +- apps/site/tsconfig.json | 1 + packages/rehype-shiki/src/plugin.mjs | 10 ++- packages/ui-components/README.md | 20 ++++++ packages/ui-components/package.json | 49 ++++++++++----- packages/ui-components/scripts/publish.mjs | 32 ---------- .../src/Common/Badge/index.module.css | 55 ++++++++++++++++ .../src/Common/BaseCodeBox/index.module.css | 27 ++++++-- .../src/Common/BaseCodeBox/index.tsx | 49 ++++++++------- .../src/Common/CodeTabs/index.module.css | 2 +- .../src/Common/DataTag/index.module.css | 55 ++++++++++++++++ .../src/Common/DataTag/index.tsx | 18 +++++- .../Common/TableOfContents/index.module.css | 7 ++- .../src/Common/TableOfContents/index.tsx | 9 ++- .../src/Common/Tabs/index.module.css | 5 +- .../src/Containers/Article/index.module.css | 22 ++++--- .../src/Containers/MetaBar/index.module.css | 5 ++ .../src/Containers/MetaBar/index.tsx | 11 +++- .../src/Containers/Sidebar/index.module.css | 7 ++- .../PartnerLogos/DigitalOcean/Favicon.tsx | 4 +- .../ui-components/src/styles/markdown.css | 63 +++++++++++++++---- packages/ui-components/tsconfig.json | 4 +- 25 files changed, 359 insertions(+), 126 deletions(-) delete mode 100644 packages/ui-components/scripts/publish.mjs diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml index d345c6b5c4118..1175b769ce0d0 100644 --- a/.github/workflows/publish-packages.yml +++ b/.github/workflows/publish-packages.yml @@ -116,10 +116,11 @@ jobs: # Check if a custom publish script exists in package.json if jq -e '.scripts.release' package.json > /dev/null; then pnpm run release - else - pnpm publish --access public --no-git-checks fi + # Then publish the package to npm + pnpm publish --access public --no-git-checks + - name: Notify on Manual Release if: ${{ github.event_name == 'workflow_dispatch' }} uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # 2.3.3 diff --git a/apps/site/components/Common/Partners/index.tsx b/apps/site/components/Common/Partners/index.tsx index 464af46b75d8b..06f7d29ae7dfd 100644 --- a/apps/site/components/Common/Partners/index.tsx +++ b/apps/site/components/Common/Partners/index.tsx @@ -1,4 +1,3 @@ -import Tooltip from '@node-core/ui-components/Common/Tooltip'; import * as PartnerLogos from '@node-core/ui-components/Icons/PartnerLogos'; import providePartners from '#site/next-data/providers/partners'; @@ -36,15 +35,15 @@ const renderSmallPartner = (partner: Partner) => { const Logo = PartnerLogos[partner.id]; return ( - {partner.name}} + size="small" + href={partner.href} + title={partner.name} > - - - - + + ); }; diff --git a/apps/site/layouts/layouts.module.css b/apps/site/layouts/layouts.module.css index 770ea8c62ef06..d4d330b807fbc 100644 --- a/apps/site/layouts/layouts.module.css +++ b/apps/site/layouts/layouts.module.css @@ -1,12 +1,12 @@ @reference "../styles/index.css"; .baseLayout { - @apply grid + @apply ml:grid + ml:grid-cols-[1fr] + ml:grid-rows-[auto_1fr_auto] h-max min-h-full - w-full - grid-cols-[1fr] - grid-rows-[auto_1fr_auto]; + w-full; } .centeredLayout { diff --git a/apps/site/next.fetch.mjs b/apps/site/next.fetch.mjs index 9a6a3250ea2b0..26eaa48925a00 100644 --- a/apps/site/next.fetch.mjs +++ b/apps/site/next.fetch.mjs @@ -26,7 +26,7 @@ export const fetchWithRetry = async ( const backoff = Math.max(0, Number(delay) || 0); const attemptFetch = attempt => - fetch(url, options).catch(e => { + fetch(url, { ...options, signal: AbortSignal.timeout(30000) }).catch(e => { if (attempt === retries || !isTimeoutError(e)) { throw e; } diff --git a/apps/site/tsconfig.json b/apps/site/tsconfig.json index a662061edf89f..6956ba1568824 100644 --- a/apps/site/tsconfig.json +++ b/apps/site/tsconfig.json @@ -10,6 +10,7 @@ "esModuleInterop": true, "module": "esnext", "moduleResolution": "Bundler", + "customConditions": ["default"], "resolveJsonModule": true, "isolatedModules": true, "jsx": "react-jsx", diff --git a/packages/rehype-shiki/src/plugin.mjs b/packages/rehype-shiki/src/plugin.mjs index 9f1663c735aff..5c3c71e73da3d 100644 --- a/packages/rehype-shiki/src/plugin.mjs +++ b/packages/rehype-shiki/src/plugin.mjs @@ -13,6 +13,11 @@ const languagePrefix = 'language-'; // The regex to match metadata const rMeta = /(\w+)(?:=(?:"([^"]+)"|(\S+)))?/g; +const getLineCount = value => + value + .split('\n') + .filter((_, i, arr) => !(i === arr.length - 1 && arr[i] === '')).length; + /** * Parses a fenced code block metadata string into a JavaScript object. * @param {string} meta - The metadata string from a Markdown code fence. @@ -165,6 +170,8 @@ export default async function rehypeShikiji(options) { // Retrieve the whole
 contents as a parsed DOM string
       const preElementContents = toString(preElement);
 
+      const lineCount = getLineCount(preElementContents);
+
       // Grabs the relevant alias/name of the language
       const languageId = codeLanguage.slice(languagePrefix.length);
 
@@ -178,7 +185,8 @@ export default async function rehypeShikiji(options) {
       // Adds the original language back to the 
 element
       children[0].properties.class = classNames(
         children[0].properties.class,
-        codeLanguage
+        codeLanguage,
+        { 'no-line-numbers': lineCount < 5, 'no-footer': lineCount === 1 }
       );
 
       // Replaces the 
 element with the updated one
diff --git a/packages/ui-components/README.md b/packages/ui-components/README.md
index f701e050751b7..b1f590f2dc541 100644
--- a/packages/ui-components/README.md
+++ b/packages/ui-components/README.md
@@ -8,3 +8,23 @@ The components are based on [this design file](https://www.figma.com/design/a10c
 Most components in this package are available on [Chromatic](https://www.chromatic.com/library?appId=64c7d71358830e9105808652).
 
 For additional details regarding specific components, refer to the [nodejs/nodejs.org](https://github.com/nodejs/nodejs.org) repository.
+
+## Local development
+
+To use this package via `npm link` in another repo (for example, doc-kit), build the
+compiled outputs and keep them updated while you work.
+
+```bash
+# From nodejs.org/packages/ui-components
+pnpm install
+node --run compile:watch
+
+# In another terminal, still in nodejs.org/packages/ui-components
+npm link
+
+# From the consumer repo (for example doc-kit)
+npm link @node-core/ui-components
+```
+
+The `compile:watch` script keeps `dist/` up to date so consumers resolve compiled
+CSS and JavaScript instead of the raw Tailwind source.
diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json
index ae4e0bb89a0de..98ec8133afae6 100644
--- a/packages/ui-components/package.json
+++ b/packages/ui-components/package.json
@@ -3,13 +3,20 @@
   "version": "1.5.10",
   "type": "module",
   "exports": {
-    "./*": [
-      "./src/*",
-      "./src/*.tsx",
-      "./src/*/index.tsx",
-      "./src/*.ts",
-      "./src/*/index.ts"
-    ]
+    "./*": {
+      "rolldown": [
+        "./dist/*",
+        "./dist/*.js",
+        "./dist/*/index.js"
+      ],
+      "default": [
+        "./src/*",
+        "./src/*.tsx",
+        "./src/*/index.tsx",
+        "./src/*.ts",
+        "./src/*/index.ts"
+      ]
+    }
   },
   "repository": {
     "type": "git",
@@ -20,7 +27,8 @@
     "compile:ts": "tsc",
     "compile:css": "postcss --dir dist --base src \"src/**/*.module.css\" src/styles/index.css",
     "compile": "node --run compile:ts && node --run compile:css",
-    "release": "node --run compile && node scripts/publish.mjs",
+    "compile:watch": "node --run compile:ts -- --watch & node --run compile:css -- --watch",
+    "release": "node --run compile",
     "lint": "node --run lint:js && node --run lint:css",
     "lint:css": "stylelint \"**/*.css\" --allow-empty-input --cache --cache-strategy=content --cache-location=.stylelintcache",
     "lint:css:fix": "node --run lint:css -- --fix",
@@ -80,14 +88,25 @@
     "typescript": "catalog:"
   },
   "imports": {
-    "#ui/*": [
-      "./src/*",
-      "./src/*.tsx",
-      "./src/*/index.tsx",
-      "./src/*.ts",
-      "./src/*/index.ts"
-    ]
+    "#ui/*": {
+      "rolldown": [
+        "./dist/*",
+        "./dist/*.js",
+        "./dist/*/index.js"
+      ],
+      "default": [
+        "./src/*",
+        "./src/*.tsx",
+        "./src/*/index.tsx",
+        "./src/*.ts",
+        "./src/*/index.ts"
+      ]
+    }
   },
+  "files": [
+    "dist/**",
+    "README.md"
+  ],
   "engines": {
     "node": ">=20"
   }
diff --git a/packages/ui-components/scripts/publish.mjs b/packages/ui-components/scripts/publish.mjs
deleted file mode 100644
index 7834b7126be0f..0000000000000
--- a/packages/ui-components/scripts/publish.mjs
+++ /dev/null
@@ -1,32 +0,0 @@
-import { spawnSync } from 'node:child_process';
-import { writeFile, copyFile } from 'node:fs/promises';
-
-import pkg from '../package.json' with { type: 'json' };
-
-// Strip the devDependencies, since they aren't needed for publish
-// Strip the exports, since we don't want to reference './src'
-/* eslint-disable @typescript-eslint/no-unused-vars */
-const { devDependencies, exports, ...cleanedPkg } = pkg;
-// Change `#ui` to `./` from `./src`, since we are publishing
-// from the same directory as the source code (rather, the compiled code).
-cleanedPkg.imports['#ui/*'] = ['./*'];
-
-await writeFile(
-  'dist/package.json',
-  JSON.stringify(cleanedPkg, null, 2),
-  'utf8'
-);
-
-await copyFile('README.md', 'dist/README.md');
-
-// Now, publish the generated `dist` folder
-const { status, error } = spawnSync('pnpm', ['publish', '--no-git-checks'], {
-  cwd: 'dist',
-  stdio: 'inherit',
-});
-
-if (error) {
-  throw error;
-}
-
-process.exitCode = status;
diff --git a/packages/ui-components/src/Common/Badge/index.module.css b/packages/ui-components/src/Common/Badge/index.module.css
index 008f025cf3d95..47faa0c351843 100644
--- a/packages/ui-components/src/Common/Badge/index.module.css
+++ b/packages/ui-components/src/Common/Badge/index.module.css
@@ -38,6 +38,61 @@
     @apply bg-neutral-800;
   }
 
+  &[data-tooltip] {
+    @apply relative
+      cursor-help;
+  }
+
+  &[data-tooltip]::after {
+    @apply pointer-events-none
+      absolute
+      top-full
+      left-1/2
+      z-10
+      mt-2
+      w-max
+      -translate-x-1/2
+      rounded-md
+      bg-neutral-900
+      px-2.5
+      py-1.5
+      text-xs
+      font-medium
+      text-white
+      opacity-0
+      transition-opacity
+      dark:bg-neutral-100
+      dark:text-neutral-900;
+
+    content: attr(data-tooltip);
+  }
+
+  &[data-tooltip]::before {
+    @apply pointer-events-none
+      absolute
+      top-full
+      left-1/2
+      z-10
+      mt-1
+      h-2
+      w-2
+      -translate-x-1/2
+      rotate-45
+      bg-neutral-900
+      opacity-0
+      transition-opacity
+      dark:bg-neutral-100;
+
+    content: '';
+  }
+
+  &[data-tooltip]:hover::after,
+  &[data-tooltip]:hover::before,
+  &[data-tooltip]:focus-visible::after,
+  &[data-tooltip]:focus-visible::before {
+    @apply opacity-100;
+  }
+
   &.circular {
     @apply font-ibm-plex-mono
       inline-flex
diff --git a/packages/ui-components/src/Common/BaseCodeBox/index.module.css b/packages/ui-components/src/Common/BaseCodeBox/index.module.css
index 923d875a9f334..d97e0a3fd33da 100644
--- a/packages/ui-components/src/Common/BaseCodeBox/index.module.css
+++ b/packages/ui-components/src/Common/BaseCodeBox/index.module.css
@@ -53,6 +53,19 @@
             [counter-increment:line];
         }
       }
+
+      &[class*='plain-text'] {
+        @apply font-mono;
+      }
+    }
+
+    &[class*='no-line-numbers'] > code > [class='line'] {
+      @apply pl-0;
+
+      &:not(:empty:last-child)::after {
+        @apply content-none
+          [counter-reset:none];
+      }
     }
   }
 
@@ -62,8 +75,8 @@
       justify-between
       border-t
       border-t-neutral-900
-      px-4
-      py-3
+      px-3
+      py-2
       text-sm
       font-medium;
 
@@ -72,9 +85,15 @@
     }
 
     & > .action {
-      @apply px-3
-        py-1.5
+      @apply px-2.5
+        py-1
+        text-xs
         font-medium;
+
+      > svg {
+        @apply h-4
+          w-4;
+      }
     }
   }
 }
diff --git a/packages/ui-components/src/Common/BaseCodeBox/index.tsx b/packages/ui-components/src/Common/BaseCodeBox/index.tsx
index c5ee36c1773b8..666127a156962 100644
--- a/packages/ui-components/src/Common/BaseCodeBox/index.tsx
+++ b/packages/ui-components/src/Common/BaseCodeBox/index.tsx
@@ -39,31 +39,27 @@ const transformCode = >(
   // being an empty string, so we need to remove it
   const lines = content.split('\n');
 
-  const extraStyle = language.length === 0 ? { fontFamily: 'monospace' } : {};
+  const extraClasses = classNames({ 'plain-text': language.length === 0 });
 
   return (
-    
-      {lines
-        .flatMap((line, lineIndex) => {
-          const columns = line.split(' ');
-
-          return [
-            
-              {columns.map((column, columnIndex) => (
-                
-                  {column}
-                  {columnIndex < columns.length - 1 &&  }
-                
-              ))}
-            ,
-            // Add a break line so the text content is formatted correctly
-            // when copying to clipboard
-            '\n',
-          ];
-        })
-        // Here we remove that empty line from before and
-        // the last flatMap entry which is an `\n`
-        .slice(0, -2)}
+    
+      {lines.flatMap((line, lineIndex) => {
+        const columns = line.split(' ');
+
+        return [
+          
+            {columns.map((column, columnIndex) => (
+              
+                {column}
+                {columnIndex < columns.length - 1 &&  }
+              
+            ))}
+          ,
+          // Add a break line so the text content is formatted correctly
+          // when copying to clipboard
+          '\n',
+        ];
+      })}
     
   );
 };
@@ -89,8 +85,11 @@ const BaseCodeBox: FC> = ({
   const containerRef = useRef(null);
 
   const handleCopy = () => copy(containerRef.current?.textContent);
+
   const ButtonIcon = copied ? DocumentDuplicateIcon : CodeBracketIcon;
 
+  const hideFooter = className?.includes('no-footer');
+
   return (
     
> = ({
       >
         {transformCode(children as ReactElement, language)}
       
- {language && ( + + {!language || hideFooter || (
{language} + = ({ kind, size = 'md' }) => ( -
+
{symbolMap[kind]}
); diff --git a/packages/ui-components/src/Common/TableOfContents/index.module.css b/packages/ui-components/src/Common/TableOfContents/index.module.css index 3e97de5dd5a7c..eac5bd455be23 100644 --- a/packages/ui-components/src/Common/TableOfContents/index.module.css +++ b/packages/ui-components/src/Common/TableOfContents/index.module.css @@ -5,7 +5,7 @@ block rounded-md bg-neutral-200 - lg:hidden + xl:hidden dark:bg-neutral-900; &[open] { @@ -49,6 +49,11 @@ dark:hover:text-neutral-500; } + .codeLink { + @apply font-ibm-plex-mono + font-medium; + } + .depthThree { @apply pl-2; } diff --git a/packages/ui-components/src/Common/TableOfContents/index.tsx b/packages/ui-components/src/Common/TableOfContents/index.tsx index 015e5c4431823..f3c0f2e4cc72d 100644 --- a/packages/ui-components/src/Common/TableOfContents/index.tsx +++ b/packages/ui-components/src/Common/TableOfContents/index.tsx @@ -13,6 +13,8 @@ const depthClasses: Record = { 4: styles.depthFour, }; +const CODE_LIKE_TYPES = new Set(['method', 'classMethod', 'function', 'ctor']); + type TableOfContentsProps = ComponentProps<'details'> & { headings: Array; summaryTitle: string; @@ -44,7 +46,12 @@ const TableOfContents: FC = ({
  • {head.value} diff --git a/packages/ui-components/src/Common/Tabs/index.module.css b/packages/ui-components/src/Common/Tabs/index.module.css index f51259c26a0b5..f700b7b1321aa 100644 --- a/packages/ui-components/src/Common/Tabs/index.module.css +++ b/packages/ui-components/src/Common/Tabs/index.module.css @@ -15,7 +15,8 @@ @apply border-b-2 border-b-transparent px-1 - pb-[11px] + pt-0 + pb-2 text-sm font-semibold whitespace-nowrap @@ -28,7 +29,7 @@ border border-neutral-200 px-1 - py-0.5 + py-0 text-xs font-normal text-neutral-200; diff --git a/packages/ui-components/src/Containers/Article/index.module.css b/packages/ui-components/src/Containers/Article/index.module.css index c4d541d9fb19f..8d3dccdfd9a8f 100644 --- a/packages/ui-components/src/Containers/Article/index.module.css +++ b/packages/ui-components/src/Containers/Article/index.module.css @@ -3,23 +3,24 @@ .articleLayout { @apply max-w-10xl ml:grid - ml:grid-cols-[--spacing(52)_1fr] + ml:grid-cols-[--spacing(56)_1fr] ml:grid-rows-[1fr] ml:overflow-visible ml:[grid-template-areas:'sidebar_main''sidebar_footer'] + 3xl:grid-cols-[--spacing(80)_1fr_--spacing(80)] mx-auto block w-full - xl:grid-cols-[--spacing(52)_1fr_--spacing(52)] + xl:grid-cols-[--spacing(56)_1fr_--spacing(64)] xl:[grid-template-areas:'sidebar_main_metabar''sidebar_footer_metabar'] - 2xl:grid-cols-[--spacing(80)_1fr_--spacing(80)]; + 2xl:grid-cols-[--spacing(72)_1fr_--spacing(72)]; > *:nth-child(1) { - @apply [grid-area:sidebar] - xl:sticky - xl:top-0 - xl:h-screen - xl:overflow-y-auto; + @apply ml:sticky + ml:top-0 + ml:h-svh + ml:overflow-y-auto + [grid-area:sidebar]; } > *:nth-child(2) { @@ -36,7 +37,8 @@ p-4 [grid-area:main] motion-safe:scroll-smooth - xl:p-12; + xl:p-10 + 2xl:p-12; } > *:last-child { @@ -46,7 +48,7 @@ [grid-area:metabar] xl:sticky xl:top-0 - xl:max-w-xs + xl:max-w-none xl:border-t-0 xl:border-l; } diff --git a/packages/ui-components/src/Containers/MetaBar/index.module.css b/packages/ui-components/src/Containers/MetaBar/index.module.css index 341c3f8b84e69..f06fc547e2668 100644 --- a/packages/ui-components/src/Containers/MetaBar/index.module.css +++ b/packages/ui-components/src/Containers/MetaBar/index.module.css @@ -59,6 +59,11 @@ } } + a.codeLink { + @apply font-ibm-plex-mono + font-medium; + } + ol { @apply flex w-full diff --git a/packages/ui-components/src/Containers/MetaBar/index.tsx b/packages/ui-components/src/Containers/MetaBar/index.tsx index c761cfe07f643..e190d80e26f32 100644 --- a/packages/ui-components/src/Containers/MetaBar/index.tsx +++ b/packages/ui-components/src/Containers/MetaBar/index.tsx @@ -6,6 +6,8 @@ import type { FC, HTMLAttributes } from 'react'; import styles from './index.module.css'; +const CODE_LIKE_TYPES = new Set(['method', 'classMethod', 'function', 'ctor']); + type MetaBarProps = { items: Partial>; headings?: { @@ -55,7 +57,14 @@ const MetaBar: FC = ({ head.depth === 3 ? 'pl-2' : head.depth === 4 ? 'pl-4' : '' } > - + {' '} {head.value} diff --git a/packages/ui-components/src/Containers/Sidebar/index.module.css b/packages/ui-components/src/Containers/Sidebar/index.module.css index f129b31b576de..a56bed69bf94b 100644 --- a/packages/ui-components/src/Containers/Sidebar/index.module.css +++ b/packages/ui-components/src/Containers/Sidebar/index.module.css @@ -1,10 +1,11 @@ @reference "../../styles/index.css"; .wrapper { - @apply scrollbar-thin - ml:max-w-xs + @apply ml:max-w-xs ml:overflow-auto ml:border-r + scrollbar-thin + ml:pb-[var(--header-height)] z-0 flex w-full @@ -14,7 +15,7 @@ border-neutral-200 bg-white px-4 - py-6 + pt-6 2xl:px-6 dark:border-neutral-900 dark:bg-neutral-950; diff --git a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx index ff97fbbeb96d8..4d59d1986b865 100644 --- a/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx +++ b/packages/ui-components/src/Icons/PartnerLogos/DigitalOcean/Favicon.tsx @@ -18,9 +18,7 @@ const DigitalOcean: FC> = props => ( a):not(h2 > a):not(h3 > a):not(h4 > a):not(h5 > a):not(h6 > a), - .anchor { + a:not(h1 > a):not(h2 > a):not(h3 > a):not(h4 > a):not(h5 > a):not(h6 > a) { @apply max-ml:font-semibold text-green-600 dark:text-green-400; @@ -98,25 +124,38 @@ main { } ul { - @apply list-disc - pr-5 - pl-9 + @apply max-ml:pr-3 + max-ml:pl-5 + list-disc + pr-4 + pl-6 leading-6 text-neutral-900 dark:text-white; + li + li { + @apply mt-2; + } + li div:has(> pre) { @apply my-1!; } } ol { - @apply list-decimal - px-5 + @apply max-ml:pr-3 + max-ml:pl-5 + list-decimal + pr-4 + pl-6 leading-6 text-neutral-900 dark:text-white; + li + li { + @apply mt-2; + } + li div:has(> pre) { @apply my-1!; } @@ -137,13 +176,15 @@ main { /* Common border and text styles */ th, td { - @apply border + @apply max-ml:px-3 + max-ml:py-1.5 + border border-t-0 border-r-0 border-neutral-200 px-4 py-2 - break-words + wrap-break-word text-neutral-900 dark:border-neutral-900 dark:text-white; @@ -218,7 +259,7 @@ main { before:-translate-y-1/2 before:text-left before:font-medium - before:break-words + before:wrap-break-word before:text-neutral-700 before:content-[attr(data-label)] last:border-0 diff --git a/packages/ui-components/tsconfig.json b/packages/ui-components/tsconfig.json index c10b5158c158f..d1b21933bc857 100644 --- a/packages/ui-components/tsconfig.json +++ b/packages/ui-components/tsconfig.json @@ -8,10 +8,12 @@ "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "module": "esnext", - "moduleResolution": "Bundler", + "moduleResolution": "bundler", + "customConditions": ["default"], "resolveJsonModule": true, "isolatedModules": true, "jsx": "react-jsx", + "declaration": true, "incremental": true, "baseUrl": "./src", "rootDir": "./src", From a9f360c9a06a9dc7854eded0c310e27ceffbb930 Mon Sep 17 00:00:00 2001 From: Claudio Wunder Date: Wed, 11 Feb 2026 01:57:33 +0100 Subject: [PATCH 2/4] fix: remove last dangling \n when present --- packages/rehype-shiki/src/plugin.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rehype-shiki/src/plugin.mjs b/packages/rehype-shiki/src/plugin.mjs index 5c3c71e73da3d..5016f7afbb79d 100644 --- a/packages/rehype-shiki/src/plugin.mjs +++ b/packages/rehype-shiki/src/plugin.mjs @@ -168,7 +168,7 @@ export default async function rehypeShikiji(options) { const meta = parseMeta(preElement.data?.meta); // Retrieve the whole
     contents as a parsed DOM string
    -      const preElementContents = toString(preElement);
    +      const preElementContents = toString(preElement).replace(/\n$/, '');
     
           const lineCount = getLineCount(preElementContents);
     
    
    From 66bb0d73311616c2b941535dd9f22d1e7c28af7a Mon Sep 17 00:00:00 2001
    From: Claudio Wunder 
    Date: Wed, 11 Feb 2026 02:44:37 +0100
    Subject: [PATCH 3/4] chore: removed motion from flashable elements, css-only
     tooltip
    
    ---
     .../site/components/Common/Partners/index.tsx |  2 +-
     apps/site/components/withMetaBar.tsx          |  8 +-
     apps/site/next-env.d.ts                       |  2 +-
     .../src/Common/Badge/index.module.css         | 55 --------------
     .../src/Common/BaseButton/index.module.css    |  5 +-
     .../src/Common/DataTag/index.module.css       | 55 --------------
     .../src/Common/Search/Modal/index.module.css  |  2 -
     .../src/Common/ThemeToggle/index.module.css   |  1 -
     .../NavBar/NavItem/index.module.css           |  3 +-
     packages/ui-components/src/styles/base.css    | 73 +++++++++++++++++++
     10 files changed, 80 insertions(+), 126 deletions(-)
    
    diff --git a/apps/site/components/Common/Partners/index.tsx b/apps/site/components/Common/Partners/index.tsx
    index 06f7d29ae7dfd..430ca83b6abb7 100644
    --- a/apps/site/components/Common/Partners/index.tsx
    +++ b/apps/site/components/Common/Partners/index.tsx
    @@ -40,7 +40,7 @@ const renderSmallPartner = (partner: Partner) => {
           key={partner.id}
           size="small"
           href={partner.href}
    -      title={partner.name}
    +      data-tooltip={partner.name}
         >
           
         
    diff --git a/apps/site/components/withMetaBar.tsx b/apps/site/components/withMetaBar.tsx
    index ca7b7f3f6a0ca..22d52a9db83c3 100644
    --- a/apps/site/components/withMetaBar.tsx
    +++ b/apps/site/components/withMetaBar.tsx
    @@ -35,11 +35,7 @@ const WithMetaBar: FC = () => {
       // Since we cannot show the same number of avatars in Mobile / Tablet
       // resolution as we do on desktop and there is overflow, we are adjusting
       // the number of avatars manually for the resolutions below
    -  const isMobileResolution = useMediaQuery('(max-width: 890px)');
    -
    -  const isTabletResolution = useMediaQuery(
    -    '(min-width: 890px) and (max-width: 1280px)'
    -  );
    +  const isSmallerThanDesktop = useMediaQuery('(max-width: 1280px)');
     
       return (
          {
               )]: (
                 
               ),
             }),
    diff --git a/apps/site/next-env.d.ts b/apps/site/next-env.d.ts
    index c05d9f7d66f17..cdb6b7b848c32 100644
    --- a/apps/site/next-env.d.ts
    +++ b/apps/site/next-env.d.ts
    @@ -1,7 +1,7 @@
     /// 
     /// 
     /// 
    -import './.next/types/routes.d.ts';
    +import './.next/dev/types/routes.d.ts';
     
     // NOTE: This file should not be edited
     // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
    diff --git a/packages/ui-components/src/Common/Badge/index.module.css b/packages/ui-components/src/Common/Badge/index.module.css
    index 47faa0c351843..008f025cf3d95 100644
    --- a/packages/ui-components/src/Common/Badge/index.module.css
    +++ b/packages/ui-components/src/Common/Badge/index.module.css
    @@ -38,61 +38,6 @@
         @apply bg-neutral-800;
       }
     
    -  &[data-tooltip] {
    -    @apply relative
    -      cursor-help;
    -  }
    -
    -  &[data-tooltip]::after {
    -    @apply pointer-events-none
    -      absolute
    -      top-full
    -      left-1/2
    -      z-10
    -      mt-2
    -      w-max
    -      -translate-x-1/2
    -      rounded-md
    -      bg-neutral-900
    -      px-2.5
    -      py-1.5
    -      text-xs
    -      font-medium
    -      text-white
    -      opacity-0
    -      transition-opacity
    -      dark:bg-neutral-100
    -      dark:text-neutral-900;
    -
    -    content: attr(data-tooltip);
    -  }
    -
    -  &[data-tooltip]::before {
    -    @apply pointer-events-none
    -      absolute
    -      top-full
    -      left-1/2
    -      z-10
    -      mt-1
    -      h-2
    -      w-2
    -      -translate-x-1/2
    -      rotate-45
    -      bg-neutral-900
    -      opacity-0
    -      transition-opacity
    -      dark:bg-neutral-100;
    -
    -    content: '';
    -  }
    -
    -  &[data-tooltip]:hover::after,
    -  &[data-tooltip]:hover::before,
    -  &[data-tooltip]:focus-visible::after,
    -  &[data-tooltip]:focus-visible::before {
    -    @apply opacity-100;
    -  }
    -
       &.circular {
         @apply font-ibm-plex-mono
           inline-flex
    diff --git a/packages/ui-components/src/Common/BaseButton/index.module.css b/packages/ui-components/src/Common/BaseButton/index.module.css
    index c45b71abfca60..4eb0e97fd2500 100644
    --- a/packages/ui-components/src/Common/BaseButton/index.module.css
    +++ b/packages/ui-components/src/Common/BaseButton/index.module.css
    @@ -9,8 +9,7 @@
         px-4.5
         py-2.5
         text-center
    -    font-semibold
    -    motion-safe:transition-colors;
    +    font-semibold;
     
       svg {
         @apply size-5;
    @@ -124,7 +123,7 @@
           after:mx-auto
           after:h-px
           after:w-2/5
    -      after:bg-gradient-to-r
    +      after:bg-linear-to-r
           after:from-green-600/0
           after:via-green-600
           after:to-green-600/0
    diff --git a/packages/ui-components/src/Common/DataTag/index.module.css b/packages/ui-components/src/Common/DataTag/index.module.css
    index cad401f7e0e27..ef244b3765153 100644
    --- a/packages/ui-components/src/Common/DataTag/index.module.css
    +++ b/packages/ui-components/src/Common/DataTag/index.module.css
    @@ -9,61 +9,6 @@
         font-semibold
         text-white;
     
    -  &[data-tooltip] {
    -    @apply relative
    -      cursor-help;
    -  }
    -
    -  &[data-tooltip]::after {
    -    @apply pointer-events-none
    -      absolute
    -      top-full
    -      left-1/2
    -      z-10
    -      mt-2
    -      w-max
    -      -translate-x-1/2
    -      rounded-md
    -      bg-neutral-900
    -      px-2.5
    -      py-1.5
    -      text-xs
    -      font-medium
    -      text-white
    -      opacity-0
    -      transition-opacity
    -      dark:bg-neutral-100
    -      dark:text-neutral-900;
    -
    -    content: attr(data-tooltip);
    -  }
    -
    -  &[data-tooltip]::before {
    -    @apply pointer-events-none
    -      absolute
    -      top-full
    -      left-1/2
    -      z-10
    -      mt-1
    -      h-2
    -      w-2
    -      -translate-x-1/2
    -      rotate-45
    -      bg-neutral-900
    -      opacity-0
    -      transition-opacity
    -      dark:bg-neutral-100;
    -
    -    content: '';
    -  }
    -
    -  &[data-tooltip]:hover::after,
    -  &[data-tooltip]:hover::before,
    -  &[data-tooltip]:focus-visible::after,
    -  &[data-tooltip]:focus-visible::before {
    -    @apply opacity-100;
    -  }
    -
       &.lg {
         @apply size-12
           text-2xl;
    diff --git a/packages/ui-components/src/Common/Search/Modal/index.module.css b/packages/ui-components/src/Common/Search/Modal/index.module.css
    index d683d4c51a183..984bc208ea834 100644
    --- a/packages/ui-components/src/Common/Search/Modal/index.module.css
    +++ b/packages/ui-components/src/Common/Search/Modal/index.module.css
    @@ -24,14 +24,12 @@
         p-1.5
         text-neutral-900
         hover:bg-neutral-100
    -    motion-safe:transition-colors
         dark:border-neutral-900
         dark:bg-neutral-950
         dark:text-neutral-200;
     
       &:hover {
         @apply bg-neutral-100
    -      motion-safe:transition-colors
           motion-safe:duration-300
           dark:bg-neutral-900;
     
    diff --git a/packages/ui-components/src/Common/ThemeToggle/index.module.css b/packages/ui-components/src/Common/ThemeToggle/index.module.css
    index e0ed8df47fddc..4bbf21b7bd44a 100644
    --- a/packages/ui-components/src/Common/ThemeToggle/index.module.css
    +++ b/packages/ui-components/src/Common/ThemeToggle/index.module.css
    @@ -5,7 +5,6 @@
         rounded-md
         p-2
         text-neutral-700
    -    motion-safe:transition-colors
         dark:text-neutral-300;
     
       &:hover {
    diff --git a/packages/ui-components/src/Containers/NavBar/NavItem/index.module.css b/packages/ui-components/src/Containers/NavBar/NavItem/index.module.css
    index 6f848a0d95c4a..be3520a41e57f 100644
    --- a/packages/ui-components/src/Containers/NavBar/NavItem/index.module.css
    +++ b/packages/ui-components/src/Containers/NavBar/NavItem/index.module.css
    @@ -6,8 +6,7 @@
         gap-2
         rounded-sm
         px-3
    -    py-2
    -    motion-safe:transition-colors;
    +    py-2;
     
       .label {
         @apply text-base
    diff --git a/packages/ui-components/src/styles/base.css b/packages/ui-components/src/styles/base.css
    index ebab370edd929..b14e196d7bdc6 100644
    --- a/packages/ui-components/src/styles/base.css
    +++ b/packages/ui-components/src/styles/base.css
    @@ -15,3 +15,76 @@ body {
         dark:bg-neutral-950
         dark:text-white;
     }
    +
    +[data-tooltip] {
    +  @apply relative
    +    cursor-help;
    +
    +  &::after {
    +    @apply pointer-events-none
    +      absolute
    +      top-full
    +      left-1/2
    +      z-10
    +      mt-2
    +      w-max
    +      max-w-64
    +      -translate-x-1/2
    +      rounded-md
    +      border
    +      border-neutral-200
    +      bg-white
    +      px-2.5
    +      py-1.5
    +      text-sm
    +      font-medium
    +      text-neutral-900
    +      opacity-0
    +      shadow-lg
    +      transition-opacity;
    +
    +    content: attr(data-tooltip);
    +  }
    +
    +  &::before {
    +    @apply pointer-events-none
    +      absolute
    +      top-full
    +      left-1/2
    +      z-10
    +      mt-1
    +      h-2
    +      w-2
    +      -translate-x-1/2
    +      rotate-45
    +      border
    +      border-r-0
    +      border-b-0
    +      border-neutral-200
    +      bg-white
    +      opacity-0
    +      transition-opacity;
    +
    +    content: '';
    +  }
    +
    +  &:hover::after,
    +  &:hover::before,
    +  &:focus-visible::after,
    +  &:focus-visible::before {
    +    @apply opacity-100;
    +  }
    +}
    +
    +[data-theme='dark'] [data-tooltip] {
    +  &::after {
    +    @apply border-neutral-900
    +      bg-neutral-950
    +      text-white;
    +  }
    +
    +  &::before {
    +    @apply border-neutral-900
    +      bg-neutral-950;
    +  }
    +}
    
    From d5a24673049d29f14b0efc193f46fcd8f1f40cdc Mon Sep 17 00:00:00 2001
    From: Claudio Wunder 
    Date: Wed, 11 Feb 2026 15:01:34 +0100
    Subject: [PATCH 4/4] chore: drop ui-components publishing changes
    
    ---
     .github/workflows/publish-packages.yml     |  5 +--
     apps/site/tsconfig.json                    |  1 -
     packages/ui-components/package.json        | 49 +++++++---------------
     packages/ui-components/scripts/publish.mjs | 32 ++++++++++++++
     packages/ui-components/tsconfig.json       |  4 +-
     5 files changed, 50 insertions(+), 41 deletions(-)
     create mode 100644 packages/ui-components/scripts/publish.mjs
    
    diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml
    index 1175b769ce0d0..d345c6b5c4118 100644
    --- a/.github/workflows/publish-packages.yml
    +++ b/.github/workflows/publish-packages.yml
    @@ -116,11 +116,10 @@ jobs:
               # Check if a custom publish script exists in package.json
               if jq -e '.scripts.release' package.json > /dev/null; then
                 pnpm run release
    +          else
    +            pnpm publish --access public --no-git-checks
               fi
     
    -          # Then publish the package to npm
    -          pnpm publish --access public --no-git-checks
    -
           - name: Notify on Manual Release
             if: ${{ github.event_name == 'workflow_dispatch' }}
             uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # 2.3.3
    diff --git a/apps/site/tsconfig.json b/apps/site/tsconfig.json
    index 6956ba1568824..a662061edf89f 100644
    --- a/apps/site/tsconfig.json
    +++ b/apps/site/tsconfig.json
    @@ -10,7 +10,6 @@
         "esModuleInterop": true,
         "module": "esnext",
         "moduleResolution": "Bundler",
    -    "customConditions": ["default"],
         "resolveJsonModule": true,
         "isolatedModules": true,
         "jsx": "react-jsx",
    diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json
    index 98ec8133afae6..ae4e0bb89a0de 100644
    --- a/packages/ui-components/package.json
    +++ b/packages/ui-components/package.json
    @@ -3,20 +3,13 @@
       "version": "1.5.10",
       "type": "module",
       "exports": {
    -    "./*": {
    -      "rolldown": [
    -        "./dist/*",
    -        "./dist/*.js",
    -        "./dist/*/index.js"
    -      ],
    -      "default": [
    -        "./src/*",
    -        "./src/*.tsx",
    -        "./src/*/index.tsx",
    -        "./src/*.ts",
    -        "./src/*/index.ts"
    -      ]
    -    }
    +    "./*": [
    +      "./src/*",
    +      "./src/*.tsx",
    +      "./src/*/index.tsx",
    +      "./src/*.ts",
    +      "./src/*/index.ts"
    +    ]
       },
       "repository": {
         "type": "git",
    @@ -27,8 +20,7 @@
         "compile:ts": "tsc",
         "compile:css": "postcss --dir dist --base src \"src/**/*.module.css\" src/styles/index.css",
         "compile": "node --run compile:ts && node --run compile:css",
    -    "compile:watch": "node --run compile:ts -- --watch & node --run compile:css -- --watch",
    -    "release": "node --run compile",
    +    "release": "node --run compile && node scripts/publish.mjs",
         "lint": "node --run lint:js && node --run lint:css",
         "lint:css": "stylelint \"**/*.css\" --allow-empty-input --cache --cache-strategy=content --cache-location=.stylelintcache",
         "lint:css:fix": "node --run lint:css -- --fix",
    @@ -88,25 +80,14 @@
         "typescript": "catalog:"
       },
       "imports": {
    -    "#ui/*": {
    -      "rolldown": [
    -        "./dist/*",
    -        "./dist/*.js",
    -        "./dist/*/index.js"
    -      ],
    -      "default": [
    -        "./src/*",
    -        "./src/*.tsx",
    -        "./src/*/index.tsx",
    -        "./src/*.ts",
    -        "./src/*/index.ts"
    -      ]
    -    }
    +    "#ui/*": [
    +      "./src/*",
    +      "./src/*.tsx",
    +      "./src/*/index.tsx",
    +      "./src/*.ts",
    +      "./src/*/index.ts"
    +    ]
       },
    -  "files": [
    -    "dist/**",
    -    "README.md"
    -  ],
       "engines": {
         "node": ">=20"
       }
    diff --git a/packages/ui-components/scripts/publish.mjs b/packages/ui-components/scripts/publish.mjs
    new file mode 100644
    index 0000000000000..7834b7126be0f
    --- /dev/null
    +++ b/packages/ui-components/scripts/publish.mjs
    @@ -0,0 +1,32 @@
    +import { spawnSync } from 'node:child_process';
    +import { writeFile, copyFile } from 'node:fs/promises';
    +
    +import pkg from '../package.json' with { type: 'json' };
    +
    +// Strip the devDependencies, since they aren't needed for publish
    +// Strip the exports, since we don't want to reference './src'
    +/* eslint-disable @typescript-eslint/no-unused-vars */
    +const { devDependencies, exports, ...cleanedPkg } = pkg;
    +// Change `#ui` to `./` from `./src`, since we are publishing
    +// from the same directory as the source code (rather, the compiled code).
    +cleanedPkg.imports['#ui/*'] = ['./*'];
    +
    +await writeFile(
    +  'dist/package.json',
    +  JSON.stringify(cleanedPkg, null, 2),
    +  'utf8'
    +);
    +
    +await copyFile('README.md', 'dist/README.md');
    +
    +// Now, publish the generated `dist` folder
    +const { status, error } = spawnSync('pnpm', ['publish', '--no-git-checks'], {
    +  cwd: 'dist',
    +  stdio: 'inherit',
    +});
    +
    +if (error) {
    +  throw error;
    +}
    +
    +process.exitCode = status;
    diff --git a/packages/ui-components/tsconfig.json b/packages/ui-components/tsconfig.json
    index d1b21933bc857..c10b5158c158f 100644
    --- a/packages/ui-components/tsconfig.json
    +++ b/packages/ui-components/tsconfig.json
    @@ -8,12 +8,10 @@
         "forceConsistentCasingInFileNames": true,
         "esModuleInterop": true,
         "module": "esnext",
    -    "moduleResolution": "bundler",
    -    "customConditions": ["default"],
    +    "moduleResolution": "Bundler",
         "resolveJsonModule": true,
         "isolatedModules": true,
         "jsx": "react-jsx",
    -    "declaration": true,
         "incremental": true,
         "baseUrl": "./src",
         "rootDir": "./src",