Skip to content

Commit d9fe39c

Browse files
Convert to/from v3 theme keys in configs and plugins (#14642)
A few theme keys have changed in v4 relative to v3: - `screens` -> `--breakpoint-*` - `colors` -> `--color-*` - `animation` -> `--animate-*` - `borderRadius` -> `--radius-*` - `boxShadow` -> `--shadow-*` When using the `theme()` function we wouldn't pick up values from the CSS for some of these. Likewise, when loading a v3 config not all of these would be pushed back into the CSS theme and they should've been. This PR addresses both of these problems.
1 parent 88b52b6 commit d9fe39c

File tree

6 files changed

+127
-4
lines changed

6 files changed

+127
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
- Ensure custom variants using the JS API have access to modifiers ([#14637](https://github.com/tailwindlabs/tailwindcss/pull/14637))
2929
- Ensure auto complete suggestions work when using `matchUtilities` ([#14589](https://github.com/tailwindlabs/tailwindcss/pull/14589))
3030
- Pass options when using `addComponents` and `matchComponents` ([#14590](https://github.com/tailwindlabs/tailwindcss/pull/14590))
31+
- Convert to/from v3 theme keys in configs and plugins ([#14642](https://github.com/tailwindlabs/tailwindcss/pull/14642))
3132
- _Upgrade (experimental)_: Ensure CSS before a layer stays unlayered when running codemods ([#14596](https://github.com/tailwindlabs/tailwindcss/pull/14596))
3233
- _Upgrade (experimental)_: Resolve issues where some prefixed candidates were not properly migrated ([#14600](https://github.com/tailwindlabs/tailwindcss/pull/14600))
3334

integrations/upgrade/js-config.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ test(
7474
@variant dark (&:where(.dark, .dark *));
7575
7676
@theme {
77-
--box-shadow-*: initial;
78-
--box-shadow-sm: 0 2px 6px rgb(15 23 42 / 0.08);
77+
--shadow-*: initial;
78+
--shadow-sm: 0 2px 6px rgb(15 23 42 / 0.08);
7979
8080
--color-*: initial;
8181
--color-red-400: #f87171;

packages/tailwindcss/src/compat/apply-config-to-theme.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ test('Config values can be merged into the theme', () => {
1919
},
2020
},
2121

22+
screens: {
23+
sm: '1234px',
24+
},
25+
26+
boxShadow: {
27+
normal: '0 1px 3px black',
28+
},
29+
30+
borderRadius: {
31+
sm: '0.33rem',
32+
},
33+
34+
animation: {
35+
blink: 'blink 1s linear infinite',
36+
},
37+
2238
fontFamily: {
2339
sans: ['Inter', 'system-ui', 'sans-serif'],
2440
mono: ['Potato Mono', { fontVariationSettings: '"XHGT" 0.7' }],
@@ -41,6 +57,10 @@ test('Config values can be merged into the theme', () => {
4157
applyConfigToTheme(design, resolvedUserConfig)
4258

4359
expect(theme.resolve('primary', ['--color'])).toEqual('#c0ffee')
60+
expect(theme.resolve('sm', ['--breakpoint'])).toEqual('1234px')
61+
expect(theme.resolve('normal', ['--shadow'])).toEqual('0 1px 3px black')
62+
expect(theme.resolve('sm', ['--radius'])).toEqual('0.33rem')
63+
expect(theme.resolve('blink', ['--animate'])).toEqual('blink 1s linear infinite')
4464
expect(theme.resolve('red-500', ['--color'])).toEqual('red')
4565
expect(theme.resolve('sans', ['--font-family'])).toEqual('Inter, system-ui, sans-serif')
4666
expect(theme.resolveWith('mono', ['--font-family'], ['--font-variation-settings'])).toEqual([

packages/tailwindcss/src/compat/apply-config-to-theme.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ export function keyPathToCssProperty(path: string[]) {
114114
if (path[0] === 'colors') path[0] = 'color'
115115
if (path[0] === 'screens') path[0] = 'breakpoint'
116116
if (path[0] === 'borderRadius') path[0] = 'radius'
117+
if (path[0] === 'boxShadow') path[0] = 'shadow'
118+
if (path[0] === 'animation') path[0] = 'animate'
117119

118120
return (
119121
path

packages/tailwindcss/src/compat/config.test.ts

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { describe, expect, test } from 'vitest'
1+
import { describe, expect, test, vi } from 'vitest'
22
import { compile, type Config } from '..'
3-
import plugin from '../plugin'
3+
import { default as plugin } from '../plugin'
44
import { flattenColorPalette } from './flatten-color-palette'
55

66
const css = String.raw
@@ -1512,3 +1512,82 @@ test('blocklisted canddiates cannot be used with `@apply`', async () => {
15121512
`[Error: Cannot apply unknown utility class: bg-white]`,
15131513
)
15141514
})
1515+
1516+
test('old theme values are merged with their renamed counterparts in the CSS theme', async () => {
1517+
let didCallPluginFn = vi.fn()
1518+
1519+
await compile(
1520+
css`
1521+
@theme reference {
1522+
--breakpoint-a: 1;
1523+
--breakpoint-b: 2;
1524+
1525+
--color-a: 1;
1526+
--color-b: 2;
1527+
1528+
--radius-a: 1;
1529+
--radius-b: 2;
1530+
1531+
--shadow-a: 1;
1532+
--shadow-b: 2;
1533+
1534+
--animate-a: 1;
1535+
--animate-b: 2;
1536+
}
1537+
1538+
@plugin "./plugin.js";
1539+
`,
1540+
{
1541+
async loadModule(id, base) {
1542+
return {
1543+
base,
1544+
module: plugin(function ({ theme }) {
1545+
didCallPluginFn()
1546+
1547+
expect(theme('screens')).toMatchObject({
1548+
a: '1',
1549+
b: '2',
1550+
})
1551+
1552+
expect(theme('screens.a')).toEqual('1')
1553+
expect(theme('screens.b')).toEqual('2')
1554+
1555+
expect(theme('colors')).toMatchObject({
1556+
a: '1',
1557+
b: '2',
1558+
})
1559+
1560+
expect(theme('colors.a')).toEqual('1')
1561+
expect(theme('colors.b')).toEqual('2')
1562+
1563+
expect(theme('borderRadius')).toMatchObject({
1564+
a: '1',
1565+
b: '2',
1566+
})
1567+
1568+
expect(theme('borderRadius.a')).toEqual('1')
1569+
expect(theme('borderRadius.b')).toEqual('2')
1570+
1571+
expect(theme('animation')).toMatchObject({
1572+
a: '1',
1573+
b: '2',
1574+
})
1575+
1576+
expect(theme('animation.a')).toEqual('1')
1577+
expect(theme('animation.b')).toEqual('2')
1578+
1579+
expect(theme('boxShadow')).toMatchObject({
1580+
a: '1',
1581+
b: '2',
1582+
})
1583+
1584+
expect(theme('boxShadow.a')).toEqual('1')
1585+
expect(theme('boxShadow.b')).toEqual('2')
1586+
}),
1587+
}
1588+
},
1589+
},
1590+
)
1591+
1592+
expect(didCallPluginFn).toHaveBeenCalled()
1593+
})

packages/tailwindcss/src/compat/config/create-compat-config.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,31 @@ export function createCompatConfig(cssTheme: Theme): UserConfig {
1313
// and only allow colors from the CSS theme.
1414
colors: ({ theme }) => theme('color', {}),
1515

16+
boxShadow: ({ theme }) => ({
17+
...defaultTheme.boxShadow,
18+
...theme('shadow', {}),
19+
}),
20+
21+
animation: ({ theme }) => ({
22+
...defaultTheme.animation,
23+
...theme('animate', {}),
24+
}),
25+
26+
borderRadius: ({ theme }) => ({
27+
...defaultTheme.borderRadius,
28+
...theme('radius', {}),
29+
}),
30+
31+
screens: ({ theme }) => ({
32+
...defaultTheme.screens,
33+
...theme('breakpoint', {}),
34+
}),
35+
1636
transitionDuration: {
1737
...defaultTheme.transitionDuration,
1838
DEFAULT: cssTheme.get(['--default-transition-duration']) ?? null,
1939
},
40+
2041
transitionTimingFunction: {
2142
...defaultTheme.transitionTimingFunction,
2243
DEFAULT: cssTheme.get(['--default-transition-timing-function']) ?? null,

0 commit comments

Comments
 (0)