diff --git a/.changeset/curvy-penguins-act.md b/.changeset/curvy-penguins-act.md new file mode 100644 index 000000000000..e36bbfbf014a --- /dev/null +++ b/.changeset/curvy-penguins-act.md @@ -0,0 +1,9 @@ +--- +'@astrojs/tailwind': major +--- + +Deprecates the integration + +Tailwind CSS now offers a Vite plugin which is the preferred way to use Tailwind 4 in Astro. Please uninstall `@astrojs/tailwind` and follow the [Tailwind documentation for manual installation](https://tailwindcss.com/docs/installation/framework-guides/astro). + +This updated major version is only provided as a convenience for existing projects until they are able to migrate to the new plugin. It offers no additional functionality and is no longer recommended, but may continue to be used in your projects until it is removed entirely. diff --git a/.changeset/four-chairs-exercise.md b/.changeset/four-chairs-exercise.md new file mode 100644 index 000000000000..906c85d34d5c --- /dev/null +++ b/.changeset/four-chairs-exercise.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Updates `astro add tailwind` to add the `@tailwindcss/vite` plugin instead of the `@astrojs/tailwind` integration diff --git a/examples/with-tailwindcss/astro.config.mjs b/examples/with-tailwindcss/astro.config.mjs index 7c7ad346f1ae..832a62b06b2f 100644 --- a/examples/with-tailwindcss/astro.config.mjs +++ b/examples/with-tailwindcss/astro.config.mjs @@ -1,8 +1,10 @@ // @ts-check import { defineConfig } from 'astro/config'; -import tailwind from '@astrojs/tailwind'; +import tailwindcss from '@tailwindcss/vite'; // https://astro.build/config export default defineConfig({ - integrations: [tailwind()], + vite: { + plugins: [tailwindcss()] + } }); diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index 5705ef08a260..dec94d27bdd0 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -11,12 +11,10 @@ }, "dependencies": { "@astrojs/mdx": "^4.0.7", - "@astrojs/tailwind": "^5.1.5", + "@tailwindcss/vite": "^4.0.0", "@types/canvas-confetti": "^1.9.0", "astro": "^5.1.10", - "autoprefixer": "^10.4.20", "canvas-confetti": "^1.9.3", - "postcss": "^8.5.1", - "tailwindcss": "^3.4.17" + "tailwindcss": "^4.0.0" } } diff --git a/examples/with-tailwindcss/src/layouts/main.astro b/examples/with-tailwindcss/src/layouts/main.astro index 63bee5d25234..0a9423176087 100644 --- a/examples/with-tailwindcss/src/layouts/main.astro +++ b/examples/with-tailwindcss/src/layouts/main.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; const { content } = Astro.props; --- diff --git a/examples/with-tailwindcss/src/pages/index.astro b/examples/with-tailwindcss/src/pages/index.astro index bde5b0d29fcb..6350a3330e7d 100644 --- a/examples/with-tailwindcss/src/pages/index.astro +++ b/examples/with-tailwindcss/src/pages/index.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; // Component Imports import Button from '../components/Button.astro'; diff --git a/examples/with-tailwindcss/src/styles/global.css b/examples/with-tailwindcss/src/styles/global.css new file mode 100644 index 000000000000..a461c505f1f0 --- /dev/null +++ b/examples/with-tailwindcss/src/styles/global.css @@ -0,0 +1 @@ +@import "tailwindcss"; \ No newline at end of file diff --git a/examples/with-tailwindcss/tailwind.config.cjs b/examples/with-tailwindcss/tailwind.config.cjs deleted file mode 100644 index 49971da79421..000000000000 --- a/examples/with-tailwindcss/tailwind.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: {}, - }, - plugins: [], -}; diff --git a/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs b/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs index 97d6c85c0de9..72d4420cfb03 100644 --- a/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs +++ b/packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs @@ -1,19 +1,13 @@ -import { fileURLToPath } from 'node:url'; -import tailwind from '@astrojs/tailwind'; import { defineConfig } from 'astro/config'; +import tailwindcss from '@tailwindcss/vite'; // https://astro.build/config export default defineConfig({ - integrations: [ - tailwind({ - configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)), - applyBaseStyles: false - }), - ], devToolbar: { enabled: false, }, vite: { + plugins: [tailwindcss()], build: { assetsInlineLimit: 0, }, diff --git a/packages/astro/e2e/fixtures/tailwindcss/package.json b/packages/astro/e2e/fixtures/tailwindcss/package.json index 12e4b09c9da6..ddcd61879c43 100644 --- a/packages/astro/e2e/fixtures/tailwindcss/package.json +++ b/packages/astro/e2e/fixtures/tailwindcss/package.json @@ -4,9 +4,8 @@ "private": true, "dependencies": { "@astrojs/tailwind": "workspace:*", + "@tailwindcss/vite": "^4.0.0", "astro": "workspace:*", - "autoprefixer": "^10.4.20", - "postcss": "^8.5.1", - "tailwindcss": "^3.4.17" + "tailwindcss": "^4.0.0" } } diff --git a/packages/astro/e2e/fixtures/tailwindcss/src/pages/index.astro b/packages/astro/e2e/fixtures/tailwindcss/src/pages/index.astro index 65bff4d4a388..c8067b436e79 100644 --- a/packages/astro/e2e/fixtures/tailwindcss/src/pages/index.astro +++ b/packages/astro/e2e/fixtures/tailwindcss/src/pages/index.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; import Button from '../components/Button.astro'; import Complex from '../components/Complex.astro'; // Component Imports diff --git a/packages/astro/e2e/fixtures/tailwindcss/src/styles/global.css b/packages/astro/e2e/fixtures/tailwindcss/src/styles/global.css new file mode 100644 index 000000000000..c74f1287f803 --- /dev/null +++ b/packages/astro/e2e/fixtures/tailwindcss/src/styles/global.css @@ -0,0 +1,7 @@ +@import 'tailwindcss'; + +@theme { + --color-dawn: #f3e9fa; + --color-dusk: #514375; + --color-midnight: #31274a; +} \ No newline at end of file diff --git a/packages/astro/e2e/fixtures/tailwindcss/tailwind.config.js b/packages/astro/e2e/fixtures/tailwindcss/tailwind.config.js deleted file mode 100644 index bcfd00edcfae..000000000000 --- a/packages/astro/e2e/fixtures/tailwindcss/tailwind.config.js +++ /dev/null @@ -1,14 +0,0 @@ -const path = require('node:path'); - -module.exports = { - content: [path.join(__dirname, 'src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}')], - theme: { - extend: { - colors: { - dawn: '#f3e9fa', - dusk: '#514375', - midnight: '#31274a', - } - } - } -}; diff --git a/packages/astro/e2e/tailwindcss.test.js b/packages/astro/e2e/tailwindcss.test.js index c86d01b0e2fe..804d54e495a1 100644 --- a/packages/astro/e2e/tailwindcss.test.js +++ b/packages/astro/e2e/tailwindcss.test.js @@ -43,7 +43,7 @@ test.describe('Tailwind CSS', () => { await expect(button, 'should have bg-purple-600').toHaveClass(/bg-purple-600/); await expect(button, 'should have background color').toHaveCSS( 'background-color', - 'rgb(147, 51, 234)', + 'oklch(0.558 0.288 302.321)', ); await expect(button, 'should have lg:py-3').toHaveClass(/lg:py-3/); @@ -66,7 +66,7 @@ test.describe('Tailwind CSS', () => { await expect(button, 'should have bg-purple-400').toHaveClass(/bg-purple-400/); await expect(button, 'should have background color').toHaveCSS( 'background-color', - 'rgb(192, 132, 252)', + 'oklch(0.714 0.203 305.504)', ); }); }); diff --git a/packages/astro/src/cli/add/index.ts b/packages/astro/src/cli/add/index.ts index 6ccd4070d5ad..c3a2e1fe793a 100644 --- a/packages/astro/src/cli/add/index.ts +++ b/packages/astro/src/cli/add/index.ts @@ -51,14 +51,7 @@ const ALIASES = new Map([ const STUBS = { ASTRO_CONFIG: `import { defineConfig } from 'astro/config';\n// https://astro.build/config\nexport default defineConfig({});`, - TAILWIND_CONFIG: `/** @type {import('tailwindcss').Config} */ -export default { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: {}, - }, - plugins: [], -}\n`, + TAILWIND_GLOBAL_CSS: `@import "tailwindcss";`, SVELTE_CONFIG: `\ import { vitePreprocess } from '@astrojs/svelte'; @@ -154,23 +147,28 @@ export async function add(names: string[], { flags }: AddOptions) { switch (installResult) { case UpdateResult.updated: { if (integrations.find((integration) => integration.id === 'tailwind')) { - await setupIntegrationConfig({ - root, - logger, + const dir = new URL('./styles/', new URL(userConfig.srcDir ?? './src/', root)); + const styles = new URL('./global.css', dir); + if (!existsSync(styles)) { + logger.info( + 'SKIP_FORMAT', + `\n ${magenta(`Astro will scaffold ${green('./src/styles/global.css')}.`)}\n`, + ); - flags, - integrationName: 'Tailwind', - possibleConfigFiles: [ - './tailwind.config.cjs', - './tailwind.config.mjs', - './tailwind.config.ts', - './tailwind.config.mts', - './tailwind.config.cts', - './tailwind.config.js', - ], - defaultConfigFile: './tailwind.config.mjs', - defaultConfigContent: STUBS.TAILWIND_CONFIG, - }); + if (await askToContinue({ flags })) { + if (!existsSync(dir)) { + await fs.mkdir(dir); + } + await fs.writeFile(styles, STUBS.TAILWIND_GLOBAL_CSS, 'utf-8'); + } else { + logger.info( + 'SKIP_FORMAT', + `\n @astrojs/tailwind requires additional configuration. Please refer to https://docs.astro.build/en/guides/integrations-guide/tailwind/`, + ); + } + } else { + logger.debug('add', `Using existing tailwind configuration`); + } } if (integrations.find((integration) => integration.id === 'svelte')) { await setupIntegrationConfig({ @@ -290,6 +288,8 @@ export async function add(names: string[], { flags }: AddOptions) { )}`, ); } + } else if (integration.id === 'tailwind') { + addVitePlugin(mod, 'tailwindcss', '@tailwindcss/vite'); } else { addIntegration(mod, integration); } @@ -358,6 +358,7 @@ export async function add(names: string[], { flags }: AddOptions) { } to your project:\n${list}`, ), ); + logger.info('SKIP_FORMAT', msg.success("Import './src/styles/global.css' in a layout")); } } @@ -456,6 +457,31 @@ function addIntegration(mod: ProxifiedModule, integration: IntegrationInfo) } } +function addVitePlugin(mod: ProxifiedModule, pluginId: string, packageName: string) { + const config = getDefaultExportOptions(mod); + + if (!mod.imports.$items.some((imp) => imp.local === pluginId)) { + mod.imports.$append({ + imported: 'default', + local: pluginId, + from: packageName, + }); + } + + config.vite ??= {}; + config.vite.plugins ??= []; + if ( + !config.vite.plugins.$ast.elements.some( + (el: ASTNode) => + el.type === 'CallExpression' && + el.callee.type === 'Identifier' && + el.callee.name === pluginId, + ) + ) { + config.vite.plugins.push(builders.functionCall(pluginId)); + } +} + export function setAdapter( mod: ProxifiedModule, adapter: IntegrationInfo, @@ -796,6 +822,13 @@ async function validateIntegrations(integrations: string[]): Promise diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist-classic.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist-classic.astro index 360a58d8d9b2..88e61a960af3 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist-classic.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist-classic.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; import NoHoistClassic from '../components/NoHoistClassic.astro'; --- diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist.astro index da1d2e9a2ce8..4512618e399c 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; import NoHoistModule from '../components/NoHoistModule.astro'; --- diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/external.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/external.astro index e5b7fda80ef6..fc37c0b28cc8 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/external.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/external.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; import Widget from '../components/Widget.astro'; import Widget2 from '../components/Widget2.astro'; --- diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/glob.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/glob.astro index 5d7c77bd5074..cb5124da6085 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/glob.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/glob.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; const components = await Astro.glob('/src/components/Glob/*'); const MyComponent = components[0].default; --- diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/inline-in-page.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/inline-in-page.astro index ce9e2733e6e9..19e7e43ef7c1 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/inline-in-page.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/inline-in-page.astro @@ -1,3 +1,6 @@ +--- +import '../styles/global.css'; +--- diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/inline.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/inline.astro index 03026e659bf8..9131b61d9701 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/inline.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/inline.astro @@ -1,4 +1,5 @@ --- +import '../styles/global.css'; import Inline from '../components/Inline.astro'; --- diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/with-styles.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/with-styles.astro index af984e7b389a..6d096fe84cbf 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/pages/with-styles.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/with-styles.astro @@ -1,3 +1,6 @@ +--- +import '../styles/global.css'; +--- diff --git a/packages/astro/test/fixtures/astro-scripts/src/styles/global.css b/packages/astro/test/fixtures/astro-scripts/src/styles/global.css new file mode 100644 index 000000000000..f173aa4cff9f --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/styles/global.css @@ -0,0 +1 @@ +@import 'tailwindcss'; \ No newline at end of file diff --git a/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs b/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs deleted file mode 100644 index f5368a76ab04..000000000000 --- a/packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], - theme: { - extend: {}, - }, - plugins: [], -} diff --git a/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs b/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs index be14fb48294e..4b4b459da0f3 100644 --- a/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs +++ b/packages/astro/test/fixtures/middleware-tailwind/astro.config.mjs @@ -1,12 +1,9 @@ -import { fileURLToPath } from 'node:url'; -import tailwind from '@astrojs/tailwind'; import { defineConfig } from 'astro/config'; +import tailwindcss from "@tailwindcss/vite" // https://astro.build/config export default defineConfig({ - integrations: [ - tailwind({ - configFile: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)), - }), - ], + vite: { + plugins: [tailwindcss()], + } }); diff --git a/packages/astro/test/fixtures/middleware-tailwind/package.json b/packages/astro/test/fixtures/middleware-tailwind/package.json index e5714c8dd9c8..748dcd581ea5 100644 --- a/packages/astro/test/fixtures/middleware-tailwind/package.json +++ b/packages/astro/test/fixtures/middleware-tailwind/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "astro": "workspace:*", - "@astrojs/tailwind": "workspace:*" + "@tailwindcss/vite": "^4.0.0", + "tailwindcss": "^4.0.0" } } diff --git a/packages/astro/test/fixtures/middleware-tailwind/src/pages/index.astro b/packages/astro/test/fixtures/middleware-tailwind/src/pages/index.astro index 038b18ac9e71..3bb3b5155712 100644 --- a/packages/astro/test/fixtures/middleware-tailwind/src/pages/index.astro +++ b/packages/astro/test/fixtures/middleware-tailwind/src/pages/index.astro @@ -1,3 +1,7 @@ +--- +import '../styles/global.css'; +--- +

Hello world