From 6f5eb987f0362d9969effe76a5691ca51bb409f3 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Tue, 5 May 2026 18:08:34 -0400 Subject: [PATCH] chore(misc): migrate tailwind v3 to v4 graph apps and nx-dev pin tailwindcss 3.4.4 with JS configs and v3 directives. tailwindcss 4.1.11 via @tailwindcss/postcss. Configs converted to CSS via @import 'tailwindcss', @plugin, @source, @custom-variant. JS tailwind.config.js files removed. Drops @tailwindcss/aspect-ratio (built-in). NXC-4430 --- graph/client/postcss.config.js | 5 +- graph/client/src/styles.css | 46 ++- graph/client/tailwind.config.js | 70 ---- graph/migrate/.storybook/tailwind.css | 26 +- graph/migrate/postcss.config.js | 11 +- .../src/lib/components/migration-card.tsx | 8 +- .../src/lib/components/migration-done.tsx | 6 +- .../src/lib/components/migration-list.tsx | 4 +- .../components/migration-settings-panel.tsx | 2 +- .../src/lib/components/migration-timeline.tsx | 32 +- graph/migrate/src/lib/migrate.tsx | 6 +- graph/migrate/tailwind.config.js | 16 - graph/ui-code-block/.storybook/tailwind.css | 30 +- graph/ui-code-block/postcss.config.js | 5 +- graph/ui-code-block/tailwind.config.js | 45 --- graph/ui-common/src/lib/multi-select.tsx | 12 +- graph/ui-icons/src/lib/technology-icon.tsx | 2 +- .../.storybook/tailwind.css | 31 +- graph/ui-project-details/postcss.config.js | 5 +- .../target-configuration-details-header.tsx | 10 +- .../src/lib/tooltips/atomizer-tooltip.tsx | 8 +- graph/ui-project-details/tailwind.config.js | 54 --- .../.storybook/tailwind-imports.css | 30 +- graph/ui-render-config/postcss.config.js | 4 +- graph/ui-render-config/tailwind.config.js | 45 --- .../lib/sidebar/activity-limit-reached.tsx | 2 +- .../src/lib/algolia-search.global.css | 8 +- nx-dev/nx-dev/package.json | 6 +- nx-dev/nx-dev/postcss.config.js | 5 +- nx-dev/nx-dev/styles/main.css | 51 ++- nx-dev/nx-dev/tailwind.config.js | 53 --- nx-dev/ui-blog/src/lib/author-detail.tsx | 2 +- nx-dev/ui-blog/src/lib/blog-entry.tsx | 4 +- nx-dev/ui-blog/src/lib/filters.tsx | 4 +- nx-dev/ui-common/src/lib/call-to-action.tsx | 6 +- nx-dev/ui-common/src/lib/champion-card.tsx | 2 +- nx-dev/ui-common/src/lib/course-video.tsx | 2 +- nx-dev/ui-common/src/lib/headers/header.tsx | 38 +- nx-dev/ui-common/src/lib/plugin-card.tsx | 8 +- nx-dev/ui-common/src/lib/testimonial-card.tsx | 2 +- nx-dev/ui-common/src/lib/version-picker.tsx | 6 +- nx-dev/ui-common/src/lib/video-modal.tsx | 2 +- nx-dev/ui-fence/src/lib/selector.tsx | 6 +- .../src/lib/tags/cards.component.tsx | 10 +- .../lib/tags/install-nx-console.component.tsx | 2 +- .../src/lib/tags/pill.component.tsx | 2 +- .../ui-markdoc/src/lib/tags/short-embed.tsx | 8 +- .../src/lib/tags/svg-animation.component.tsx | 2 +- package.json | 7 +- pnpm-lock.yaml | 336 ++++-------------- 50 files changed, 388 insertions(+), 699 deletions(-) delete mode 100644 graph/client/tailwind.config.js delete mode 100644 graph/migrate/tailwind.config.js delete mode 100644 graph/ui-code-block/tailwind.config.js delete mode 100644 graph/ui-project-details/tailwind.config.js delete mode 100644 graph/ui-render-config/tailwind.config.js delete mode 100644 nx-dev/nx-dev/tailwind.config.js diff --git a/graph/client/postcss.config.js b/graph/client/postcss.config.js index b8705a0910695..eea816d32a5e0 100644 --- a/graph/client/postcss.config.js +++ b/graph/client/postcss.config.js @@ -1,6 +1,3 @@ module.exports = { - plugins: [ - require('tailwindcss')({ config: './tailwind.config.js' }), - require('autoprefixer'), - ], + plugins: [require('@tailwindcss/postcss'), require('autoprefixer')], }; diff --git a/graph/client/src/styles.css b/graph/client/src/styles.css index 88e771941b23d..fc2c4628fd027 100644 --- a/graph/client/src/styles.css +++ b/graph/client/src/styles.css @@ -2,9 +2,49 @@ @import './syntax-highlight.css'; /*! purgecss end ignore */ -@tailwind components; -@tailwind base; -@tailwind utilities; +@import 'tailwindcss'; + +@plugin '@tailwindcss/typography'; +@plugin '@tailwindcss/forms' { + strategy: class; +} + +@custom-variant dark (&:where(.dark, .dark *)); + +@source '../src'; +@source '../../ui-code-block/src'; +@source '../../ui-common/src'; +@source '../../ui-icons/src'; +@source '../../ui-project-details/src'; +@source '../../ui-render-config/src'; +@source '../../shared/src'; +@source '../../../node_modules/@nx/graph'; + +@source not '../../**/*.{spec,test,stories}.*'; +@source not '../../**/eslint.config.*'; + +/* v3 compat: default border color was gray-200, v4 is currentColor. */ +@layer base { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentColor); + } +} + +/* Strip default quote characters around inline code and blockquote. */ +.prose :where(code):not(:where([class~='not-prose'] *))::before, +.prose :where(code):not(:where([class~='not-prose'] *))::after, +.prose + :where(blockquote p:first-of-type):not( + :where([class~='not-prose'] *) + )::before, +.prose + :where(blockquote p:last-of-type):not(:where([class~='not-prose'] *))::after { + content: ''; +} /** Scrollbars **/ .dark { diff --git a/graph/client/tailwind.config.js b/graph/client/tailwind.config.js deleted file mode 100644 index a43fb421229d7..0000000000000 --- a/graph/client/tailwind.config.js +++ /dev/null @@ -1,70 +0,0 @@ -// @ts-check - -const path = require('node:path'); - -// Ignore these nx related dependencies since they are the installed versions not the ones in the workspace -// nx-ignore-next-line -const { workspaceRoot } = require('@nx/devkit'); - -const glob = '**/!(*.stories|*.spec).{js,ts,jsx,tsx,html}'; - -module.exports = { - content: [ - path.join(__dirname, 'src', glob), - // Enumerate ui-* dirs explicitly. The previous `ui-*/src/**` wildcard - // forced Tailwind to readdir the parent `graph/` to enumerate matches, - // which it then reported to postcss-loader as a context dependency. That - // caused webpack to hash every file under `graph/` (including unrelated - // siblings like graph/client-e2e and the pnpm symlink chain into - // packages/{nx,devkit}) for snapshot validation. Listing each leaf dir - // here keeps Tailwind's directory enumeration scoped per-project and - // prevents that walk. Add entries here when new graph ui-* projects are - // introduced. - path.join(__dirname, '..', 'ui-code-block/src', glob), - path.join(__dirname, '..', 'ui-common/src', glob), - path.join(__dirname, '..', 'ui-icons/src', glob), - path.join(__dirname, '..', 'ui-project-details/src', glob), - path.join(__dirname, '..', 'ui-render-config/src', glob), - path.join(__dirname, '..', 'shared/src', glob), - // Resolve the classes used in @nx/graph components - // TODO: make a decision on whether this is really the best approach, or if precompiling and deduplicating the classes would be better - path.join(workspaceRoot, 'node_modules/@nx/graph', glob), - ], - darkMode: 'class', // or 'media' or 'class' - theme: { - data: { - checked: 'headlessui-state~="checked"', - }, - extend: { - typography: { - DEFAULT: { - css: { - 'code::before': { - content: '', - }, - 'code::after': { - content: '', - }, - 'blockquote p:first-of-type::before': { - content: '', - }, - 'blockquote p:last-of-type::after': { - content: '', - }, - }, - }, - }, - }, - }, - variants: { - extend: { - translate: ['group-hover'], - }, - }, - plugins: [ - require('@tailwindcss/typography'), - require('@tailwindcss/forms')({ - strategy: 'class', - }), - ], -}; diff --git a/graph/migrate/.storybook/tailwind.css b/graph/migrate/.storybook/tailwind.css index dd1df597d08f4..7e667af9dea6e 100644 --- a/graph/migrate/.storybook/tailwind.css +++ b/graph/migrate/.storybook/tailwind.css @@ -1,6 +1,26 @@ -@tailwind components; -@tailwind base; -@tailwind utilities; +@import 'tailwindcss'; + +@source '../src'; +@source '../../ui-code-block/src'; +@source '../../ui-common/src'; +@source '../../ui-icons/src'; +@source '../../ui-project-details/src'; +@source '../../ui-render-config/src'; +@source '../../shared/src'; + +@source not '../../**/*.spec.*'; +@source not '../../**/eslint.config.*'; + +/* v3 compat: default border color was gray-200, v4 is currentColor. */ +@layer base { + *, + ::after, + ::before, + ::backdrop, + ::file-selector-button { + border-color: var(--color-gray-200, currentColor); + } +} @keyframes fadeIn { from { diff --git a/graph/migrate/postcss.config.js b/graph/migrate/postcss.config.js index c72626d6ce70c..b4bee663546e3 100644 --- a/graph/migrate/postcss.config.js +++ b/graph/migrate/postcss.config.js @@ -1,15 +1,6 @@ -const { join } = require('path'); - -// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build -// option from your application's configuration (i.e. project.json). -// -// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries - module.exports = { plugins: { - tailwindcss: { - config: join(__dirname, 'tailwind.config.js'), - }, + '@tailwindcss/postcss': {}, autoprefixer: {}, }, }; diff --git a/graph/migrate/src/lib/components/migration-card.tsx b/graph/migrate/src/lib/components/migration-card.tsx index 837140af004f0..a416fe5c1760d 100644 --- a/graph/migrate/src/lib/components/migration-card.tsx +++ b/graph/migrate/src/lib/components/migration-card.tsx @@ -245,7 +245,7 @@ export const MigrationCard = forwardRef< )} {onRunMigration && !isStopped && ( {isFailed && ( diff --git a/graph/migrate/src/lib/components/migration-timeline.tsx b/graph/migrate/src/lib/components/migration-timeline.tsx index 85ddaca7d7aca..4d50f68c5d1c2 100644 --- a/graph/migrate/src/lib/components/migration-timeline.tsx +++ b/graph/migrate/src/lib/components/migration-timeline.tsx @@ -145,7 +145,7 @@ export function MigrationTimeline({ {onCancel && ( @@ -156,7 +156,7 @@ export function MigrationTimeline({ {/* Timeline lines */} {/* Solid line for visible migrations */}
@@ -217,7 +217,7 @@ export function MigrationTimeline({
toggleMigrationExpanded(migration.id)} - className={`flex-shrink-0 cursor-pointer whitespace-nowrap text-base ${ + className={`flex-shrink-0 cursor-pointer text-base whitespace-nowrap ${ nxConsoleMetadata.completedMigrations?.[ migration.id ]?.type === 'successful' @@ -244,7 +244,7 @@ export function MigrationTimeline({ onRunMigration(migration); }} type="button" - className="flex items-center gap-2 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm transition-colors hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300 hover:dark:bg-slate-700" + className="flex items-center gap-2 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-xs transition-colors hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300 hover:dark:bg-slate-700" >
@@ -348,7 +348,7 @@ export function MigrationTimeline({ onRunMigration(currentMigration); }} type="button" - className="flex items-center gap-2 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm transition-colors hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300 hover:dark:bg-slate-700" + className="flex items-center gap-2 rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-xs transition-colors hover:bg-slate-50 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-300 hover:dark:bg-slate-700" >