Skip to content

Commit 30bbe51

Browse files
Improve compatibility with @tailwindcss/typography and @tailwindcss/forms (#14221)
This PR enables compatibility for the `@tailwindcss/typography` and `@tailwindcss/forms` plugins. This required the addition of new Plugin APIs and new package exports. ## New Plugin APIs and compatibility improvements We added support for `addComponents`, `matchComponents`, and `prefix`. The component APIs are an alias for the utilities APIs because the sorting in V4 is different and emitting components in a custom `@layer` is not necessary. Since `prefix` is not supported in V4, the `prefix()` API is currently an identity function. ```js addComponents({ '.btn': { padding: '.5rem 1rem', borderRadius: '.25rem', fontWeight: '600', }, '.btn-blue': { backgroundColor: '#3490dc', color: '#fff', '&:hover': { backgroundColor: '#2779bd', }, }, '.btn-red': { backgroundColor: '#e3342f', color: '#fff', '&:hover': { backgroundColor: '#cc1f1a', }, }, }) ``` The behavioral changes effect the `addUtilities` and `matchUtilities` functions, we now: - Allow arrays of CSS property objects to be emitted: ```js addUtilities({ '.text-trim': [ {'text-box-trim': 'both'}, {'text-box-edge': 'cap alphabetic'}, ], }) ``` - Allow arrays of utilities ```js addUtilities([ { '.text-trim':{ 'text-box-trim': 'both', 'text-box-edge': 'cap alphabetic', }, } ]) ``` - Allow more complicated selector names ```js addUtilities({ '.form-input, .form-select, .form-radio': { /* styles here */ }, '.form-input::placeholder': { /* styles here */ }, '.form-checkbox:indeterminate:checked': { /* styles here */ } }) ``` ## New `tailwindcss/color` and `tailwindcss/defaultTheme` export To be compatible to v3, we're adding two new exports to the tailwindcss package. These match the default theme values as defined in v3: ```ts import colors from 'tailwindcss/colors' console.log(colors.red[600]) ``` ```ts import theme from 'tailwindcss/defaultTheme' console.log(theme.spacing[4]) ``` --------- Co-authored-by: Philipp Spiess <hello@philippspiess.com>
1 parent 84ebe19 commit 30bbe51

15 files changed

+2373
-860
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Add support for `addBase` plugins using the `@plugin` directive ([#14172](https://github.com/tailwindlabs/tailwindcss/pull/14172))
1313
- Add support for the `tailwindcss/plugin` export ([#14173](https://github.com/tailwindlabs/tailwindcss/pull/14173))
1414
- Add support for the `theme()` function in plugins ([#14207](https://github.com/tailwindlabs/tailwindcss/pull/14207))
15+
- Add support for `addComponents`, `matchComponents`, `prefix` plugin APIs ([#14221](https://github.com/tailwindlabs/tailwindcss/pull/14221))
16+
- Add support for `tailwindcss/colors` and `tailwindcss/defaultTheme` exports for use with plugins ([#14221](https://github.com/tailwindlabs/tailwindcss/pull/14221))
17+
- Add support for the `@tailwindcss/typography` and `@tailwindcss/forms` plugins ([#14221](https://github.com/tailwindlabs/tailwindcss/pull/14221))
1518

1619
### Fixed
1720

integrations/cli/plugins.test.ts

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { candidate, css, html, json, test } from '../utils'
2+
3+
test(
4+
'builds the typography plugin utilities',
5+
{
6+
fs: {
7+
'package.json': json`
8+
{
9+
"dependencies": {
10+
"@tailwindcss/typography": "^0.5.14",
11+
"tailwindcss": "workspace:^",
12+
"@tailwindcss/cli": "workspace:^"
13+
}
14+
}
15+
`,
16+
'index.html': html`
17+
<div className="prose">
18+
<h1>Headline</h1>
19+
<p>
20+
Until now, trying to style an article, document, or blog post with Tailwind has been a
21+
tedious task that required a keen eye for typography and a lot of complex custom CSS.
22+
</p>
23+
</div>
24+
`,
25+
'src/index.css': css`
26+
@import 'tailwindcss';
27+
@plugin '@tailwindcss/typography';
28+
`,
29+
},
30+
},
31+
async ({ fs, exec }) => {
32+
await exec('pnpm tailwindcss --input src/index.css --output dist/out.css')
33+
34+
await fs.expectFileToContain('dist/out.css', [
35+
candidate`prose`,
36+
':where(h1):not(:where([class~="not-prose"],[class~="not-prose"] *))',
37+
':where(tbody td, tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *))',
38+
])
39+
},
40+
)
41+
42+
test(
43+
'builds the forms plugin utilities',
44+
{
45+
fs: {
46+
'package.json': json`
47+
{
48+
"dependencies": {
49+
"@tailwindcss/forms": "^0.5.7",
50+
"tailwindcss": "workspace:^",
51+
"@tailwindcss/cli": "workspace:^"
52+
}
53+
}
54+
`,
55+
'index.html': html`
56+
<input type="text" class="form-input" />
57+
<textarea class="form-textarea"></textarea>
58+
`,
59+
'src/index.css': css`
60+
@import 'tailwindcss';
61+
@plugin '@tailwindcss/forms';
62+
`,
63+
},
64+
},
65+
async ({ fs, exec }) => {
66+
await exec('pnpm tailwindcss --input src/index.css --output dist/out.css')
67+
68+
await fs.expectFileToContain('dist/out.css', [
69+
//
70+
candidate`form-input`,
71+
candidate`form-textarea`,
72+
])
73+
await fs.expectFileNotToContain('dist/out.css', [
74+
//
75+
candidate`form-radio`,
76+
])
77+
},
78+
)

integrations/utils.ts

+13
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ interface TestContext {
3838
read(filePath: string): Promise<string>
3939
glob(pattern: string): Promise<[string, string][]>
4040
expectFileToContain(filePath: string, contents: string | string[]): Promise<void>
41+
expectFileNotToContain(filePath: string, contents: string | string[]): Promise<void>
4142
}
4243
}
4344
type TestCallback = (context: TestContext) => Promise<void> | void
@@ -289,9 +290,21 @@ export function test(
289290
}
290291
})
291292
},
293+
async expectFileNotToContain(filePath, contents) {
294+
return retryAssertion(async () => {
295+
let fileContent = await this.read(filePath)
296+
for (let content of contents) {
297+
expect(fileContent).not.toContain(content)
298+
}
299+
})
300+
},
292301
},
293302
} satisfies TestContext
294303

304+
config.fs['.gitignore'] ??= txt`
305+
node_modules/
306+
`
307+
295308
for (let [filename, content] of Object.entries(config.fs)) {
296309
await context.fs.write(filename, content)
297310
}

packages/tailwindcss/package.json

+17-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@
2323
"require": "./dist/lib.js",
2424
"import": "./src/index.ts"
2525
},
26+
"./colors": {
27+
"require": "./src/compat/colors.cts",
28+
"import": "./src/compat/colors.ts"
29+
},
30+
"./defaultTheme": {
31+
"require": "./src/compat/default-theme.cts",
32+
"import": "./src/compat/default-theme.ts"
33+
},
2634
"./plugin": {
2735
"require": "./src/plugin.cts",
2836
"import": "./src/plugin.ts"
@@ -49,7 +57,15 @@
4957
},
5058
"./plugin": {
5159
"require": "./dist/plugin.js",
52-
"import": "./src/plugin.mjs"
60+
"import": "./dist/plugin.mjs"
61+
},
62+
"./defaultTheme": {
63+
"require": "./dist/default-theme.js",
64+
"import": "./dist/default-theme.mjs"
65+
},
66+
"./colors": {
67+
"require": "./dist/colors.js",
68+
"import": "./dist/colors.mjs"
5369
},
5470
"./package.json": "./package.json",
5571
"./index.css": "./index.css",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('./colors.ts').default

0 commit comments

Comments
 (0)