Add codemod for migrating the @screen directive (#14749)

This PR adds a codemod for migrating the old `@screen` directive from Tailwind
CSS v2 that also worked in Tailwind CSS v3 but wasn't documented anymore.

Internally, this first migrates `@screen md` to `@media screen(md)`, then we rely on the existing migration that migrates the `screen(…)` function.

Input:
```css
@screen md {
  .foo {
    color: red;
  }
}
```

Output (IR):
```css
@media screen(md) {
  .foo {
    color: red;
  }
}
```

Output:
```css
@media theme(--breakpoint-md) {
  .foo {
    color: red;
  }
}
```
This commit is contained in:
RobinMalfait 2024-10-22 16:09:55 +00:00
parent 5bf2efb521
commit 02cb52ad38
3 changed files with 26 additions and 0 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- _Upgrade (experimental)_: Migrate `plugins` with options to CSS ([#14700](https://github.com/tailwindlabs/tailwindcss/pull/14700))
- _Upgrade (experimental)_: Allow JS configuration files with `corePlugins` options to be migrated to CSS ([#14742](https://github.com/tailwindlabs/tailwindcss/pull/14742))
- _Upgrade (experimental)_: Migrate `@variants` and `@responsive` directives ([#14748](https://github.com/tailwindlabs/tailwindcss/pull/14748))
- _Upgrade (experimental)_: Migrate `@screen` directive ([#14749](https://github.com/tailwindlabs/tailwindcss/pull/14749))
### Fixed

View File

@ -41,6 +41,24 @@ it('should migrate a built-in breakpoint', async () => {
`)
})
it('should migrate `@screen` with a built-in breakpoint', async () => {
expect(
await migrate(css`
@screen md {
.foo {
color: red;
}
}
`),
).toMatchInlineSnapshot(`
"@media (width >= theme(--breakpoint-md)) {
.foo {
color: red;
}
}"
`)
})
it('should migrate a custom min-width screen (string)', async () => {
expect(
await migrate(

View File

@ -24,6 +24,13 @@ export function migrateMediaScreen({
return value ? buildMediaQuery(value) : null
})
// First migrate `@screen md` to `@media screen(md)`
root.walkAtRules('screen', (node) => {
node.name = 'media'
node.params = `screen(${node.params})`
})
// Then migrate the `screen(…)` function
root.walkAtRules((rule) => {
if (rule.name !== 'media') return