Skip to content

Commit 2ed4bd9

Browse files
florian-lefebvreHiDeoosarah11918
authored
feat(tailwind): support v4 (#13049)
Co-authored-by: HiDeoo <[email protected]> Co-authored-by: Sarah Rainsberger <[email protected]>
1 parent db252e0 commit 2ed4bd9

40 files changed

+547
-265
lines changed

.changeset/curvy-penguins-act.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@astrojs/tailwind': major
3+
---
4+
5+
Deprecates the integration
6+
7+
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).
8+
9+
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.

.changeset/four-chairs-exercise.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Updates `astro add tailwind` to add the `@tailwindcss/vite` plugin instead of the `@astrojs/tailwind` integration
+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// @ts-check
22
import { defineConfig } from 'astro/config';
3-
import tailwind from '@astrojs/tailwind';
3+
import tailwindcss from '@tailwindcss/vite';
44

55
// https://astro.build/config
66
export default defineConfig({
7-
integrations: [tailwind()],
7+
vite: {
8+
plugins: [tailwindcss()]
9+
}
810
});

examples/with-tailwindcss/package.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@
1111
},
1212
"dependencies": {
1313
"@astrojs/mdx": "^4.0.7",
14-
"@astrojs/tailwind": "^5.1.5",
14+
"@tailwindcss/vite": "^4.0.0",
1515
"@types/canvas-confetti": "^1.9.0",
1616
"astro": "^5.1.10",
17-
"autoprefixer": "^10.4.20",
1817
"canvas-confetti": "^1.9.3",
19-
"postcss": "^8.5.1",
20-
"tailwindcss": "^3.4.17"
18+
"tailwindcss": "^4.0.0"
2119
}
2220
}

examples/with-tailwindcss/src/layouts/main.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
const { content } = Astro.props;
34
---
45

examples/with-tailwindcss/src/pages/index.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
// Component Imports
34
import Button from '../components/Button.astro';
45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import "tailwindcss";

examples/with-tailwindcss/tailwind.config.cjs

-7
This file was deleted.

packages/astro/e2e/fixtures/tailwindcss/astro.config.mjs

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1-
import { fileURLToPath } from 'node:url';
2-
import tailwind from '@astrojs/tailwind';
31
import { defineConfig } from 'astro/config';
2+
import tailwindcss from '@tailwindcss/vite';
43

54
// https://astro.build/config
65
export default defineConfig({
7-
integrations: [
8-
tailwind({
9-
configFile: fileURLToPath(new URL('./tailwind.config.js', import.meta.url)),
10-
applyBaseStyles: false
11-
}),
12-
],
136
devToolbar: {
147
enabled: false,
158
},
169
vite: {
10+
plugins: [tailwindcss()],
1711
build: {
1812
assetsInlineLimit: 0,
1913
},

packages/astro/e2e/fixtures/tailwindcss/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
"private": true,
55
"dependencies": {
66
"@astrojs/tailwind": "workspace:*",
7+
"@tailwindcss/vite": "^4.0.0",
78
"astro": "workspace:*",
8-
"autoprefixer": "^10.4.20",
9-
"postcss": "^8.5.1",
10-
"tailwindcss": "^3.4.17"
9+
"tailwindcss": "^4.0.0"
1110
}
1211
}

packages/astro/e2e/fixtures/tailwindcss/src/pages/index.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
import Button from '../components/Button.astro';
34
import Complex from '../components/Complex.astro';
45
// Component Imports
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import 'tailwindcss';
2+
3+
@theme {
4+
--color-dawn: #f3e9fa;
5+
--color-dusk: #514375;
6+
--color-midnight: #31274a;
7+
}

packages/astro/e2e/fixtures/tailwindcss/tailwind.config.js

-14
This file was deleted.

packages/astro/e2e/tailwindcss.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ test.describe('Tailwind CSS', () => {
4343
await expect(button, 'should have bg-purple-600').toHaveClass(/bg-purple-600/);
4444
await expect(button, 'should have background color').toHaveCSS(
4545
'background-color',
46-
'rgb(147, 51, 234)',
46+
'oklch(0.558 0.288 302.321)',
4747
);
4848

4949
await expect(button, 'should have lg:py-3').toHaveClass(/lg:py-3/);
@@ -66,7 +66,7 @@ test.describe('Tailwind CSS', () => {
6666
await expect(button, 'should have bg-purple-400').toHaveClass(/bg-purple-400/);
6767
await expect(button, 'should have background color').toHaveCSS(
6868
'background-color',
69-
'rgb(192, 132, 252)',
69+
'oklch(0.714 0.203 305.504)',
7070
);
7171
});
7272
});

packages/astro/src/cli/add/index.ts

+57-24
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,7 @@ const ALIASES = new Map([
5151

5252
const STUBS = {
5353
ASTRO_CONFIG: `import { defineConfig } from 'astro/config';\n// https://astro.build/config\nexport default defineConfig({});`,
54-
TAILWIND_CONFIG: `/** @type {import('tailwindcss').Config} */
55-
export default {
56-
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
57-
theme: {
58-
extend: {},
59-
},
60-
plugins: [],
61-
}\n`,
54+
TAILWIND_GLOBAL_CSS: `@import "tailwindcss";`,
6255
SVELTE_CONFIG: `\
6356
import { vitePreprocess } from '@astrojs/svelte';
6457
@@ -154,23 +147,28 @@ export async function add(names: string[], { flags }: AddOptions) {
154147
switch (installResult) {
155148
case UpdateResult.updated: {
156149
if (integrations.find((integration) => integration.id === 'tailwind')) {
157-
await setupIntegrationConfig({
158-
root,
159-
logger,
150+
const dir = new URL('./styles/', new URL(userConfig.srcDir ?? './src/', root));
151+
const styles = new URL('./global.css', dir);
152+
if (!existsSync(styles)) {
153+
logger.info(
154+
'SKIP_FORMAT',
155+
`\n ${magenta(`Astro will scaffold ${green('./src/styles/global.css')}.`)}\n`,
156+
);
160157

161-
flags,
162-
integrationName: 'Tailwind',
163-
possibleConfigFiles: [
164-
'./tailwind.config.cjs',
165-
'./tailwind.config.mjs',
166-
'./tailwind.config.ts',
167-
'./tailwind.config.mts',
168-
'./tailwind.config.cts',
169-
'./tailwind.config.js',
170-
],
171-
defaultConfigFile: './tailwind.config.mjs',
172-
defaultConfigContent: STUBS.TAILWIND_CONFIG,
173-
});
158+
if (await askToContinue({ flags })) {
159+
if (!existsSync(dir)) {
160+
await fs.mkdir(dir);
161+
}
162+
await fs.writeFile(styles, STUBS.TAILWIND_GLOBAL_CSS, 'utf-8');
163+
} else {
164+
logger.info(
165+
'SKIP_FORMAT',
166+
`\n @astrojs/tailwind requires additional configuration. Please refer to https://docs.astro.build/en/guides/integrations-guide/tailwind/`,
167+
);
168+
}
169+
} else {
170+
logger.debug('add', `Using existing tailwind configuration`);
171+
}
174172
}
175173
if (integrations.find((integration) => integration.id === 'svelte')) {
176174
await setupIntegrationConfig({
@@ -290,6 +288,8 @@ export async function add(names: string[], { flags }: AddOptions) {
290288
)}`,
291289
);
292290
}
291+
} else if (integration.id === 'tailwind') {
292+
addVitePlugin(mod, 'tailwindcss', '@tailwindcss/vite');
293293
} else {
294294
addIntegration(mod, integration);
295295
}
@@ -358,6 +358,7 @@ export async function add(names: string[], { flags }: AddOptions) {
358358
} to your project:\n${list}`,
359359
),
360360
);
361+
logger.info('SKIP_FORMAT', msg.success("Import './src/styles/global.css' in a layout"));
361362
}
362363
}
363364

@@ -456,6 +457,31 @@ function addIntegration(mod: ProxifiedModule<any>, integration: IntegrationInfo)
456457
}
457458
}
458459

460+
function addVitePlugin(mod: ProxifiedModule<any>, pluginId: string, packageName: string) {
461+
const config = getDefaultExportOptions(mod);
462+
463+
if (!mod.imports.$items.some((imp) => imp.local === pluginId)) {
464+
mod.imports.$append({
465+
imported: 'default',
466+
local: pluginId,
467+
from: packageName,
468+
});
469+
}
470+
471+
config.vite ??= {};
472+
config.vite.plugins ??= [];
473+
if (
474+
!config.vite.plugins.$ast.elements.some(
475+
(el: ASTNode) =>
476+
el.type === 'CallExpression' &&
477+
el.callee.type === 'Identifier' &&
478+
el.callee.name === pluginId,
479+
)
480+
) {
481+
config.vite.plugins.push(builders.functionCall(pluginId));
482+
}
483+
}
484+
459485
export function setAdapter(
460486
mod: ProxifiedModule<any>,
461487
adapter: IntegrationInfo,
@@ -796,6 +822,13 @@ async function validateIntegrations(integrations: string[]): Promise<Integration
796822
);
797823
}
798824

825+
if (integration === 'tailwind') {
826+
dependencies = [
827+
['@tailwindcss/vite', '^4.0.0'],
828+
['tailwindcss', '^4.0.0'],
829+
];
830+
}
831+
799832
return { id: integration, packageName, dependencies, type: integrationType };
800833
}),
801834
);
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
import { fileURLToPath } from 'node:url';
2-
import tailwind from '@astrojs/tailwind';
31
import { defineConfig } from 'astro/config';
2+
import tailwindcss from '@tailwindcss/vite';
43

54
export default defineConfig({
6-
integrations: [
7-
tailwind({
8-
configFile: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)),
9-
}),
10-
],
5+
vite: {
6+
plugins: [tailwindcss()]
7+
}
118
});

packages/astro/test/fixtures/astro-scripts/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"dependencies": {
66
"astro": "workspace:*",
7-
"@astrojs/tailwind": "workspace:*"
7+
"@tailwindcss/vite": "^4.0.0",
8+
"tailwindcss": "^4.0.0"
89
}
910
}

packages/astro/test/fixtures/astro-scripts/src/external-page.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import './styles/global.css';
23
---
34

45
<html lang="en">

packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist-classic.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
import NoHoistClassic from '../components/NoHoistClassic.astro';
34
---
45

packages/astro/test/fixtures/astro-scripts/src/pages/external-no-hoist.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
import NoHoistModule from '../components/NoHoistModule.astro';
34
---
45

packages/astro/test/fixtures/astro-scripts/src/pages/external.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
import Widget from '../components/Widget.astro';
34
import Widget2 from '../components/Widget2.astro';
45
---

packages/astro/test/fixtures/astro-scripts/src/pages/glob.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
const components = await Astro.glob('/src/components/Glob/*');
34
const MyComponent = components[0].default;
45
---

packages/astro/test/fixtures/astro-scripts/src/pages/inline-in-page.astro

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
---
2+
import '../styles/global.css';
3+
---
14

25
<html>
36
<head>

packages/astro/test/fixtures/astro-scripts/src/pages/inline.astro

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import '../styles/global.css';
23
import Inline from '../components/Inline.astro';
34
---
45

packages/astro/test/fixtures/astro-scripts/src/pages/with-styles.astro

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
---
2+
import '../styles/global.css';
3+
---
14

25
<html>
36
<head>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import 'tailwindcss';

packages/astro/test/fixtures/astro-scripts/tailwind.config.cjs

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
import { fileURLToPath } from 'node:url';
2-
import tailwind from '@astrojs/tailwind';
31
import { defineConfig } from 'astro/config';
2+
import tailwindcss from "@tailwindcss/vite"
43

54
// https://astro.build/config
65
export default defineConfig({
7-
integrations: [
8-
tailwind({
9-
configFile: fileURLToPath(new URL('./tailwind.config.cjs', import.meta.url)),
10-
}),
11-
],
6+
vite: {
7+
plugins: [tailwindcss()],
8+
}
129
});

packages/astro/test/fixtures/middleware-tailwind/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"dependencies": {
66
"astro": "workspace:*",
7-
"@astrojs/tailwind": "workspace:*"
7+
"@tailwindcss/vite": "^4.0.0",
8+
"tailwindcss": "^4.0.0"
89
}
910
}

packages/astro/test/fixtures/middleware-tailwind/src/pages/index.astro

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
---
2+
import '../styles/global.css';
3+
---
4+
15
<h1 class="text-blue-500 text-2xl font-bold">Hello world</h1>
26

37
<style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import 'tailwindcss';

0 commit comments

Comments
 (0)