diff --git a/CHANGELOG.md b/CHANGELOG.md
index 79811ca5e..f4d978fe8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,8 @@ 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
@@ -20,11 +22,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add `postcss` as a dependency of `@tailwindcss/postcss` ([#14750](https://github.com/tailwindlabs/tailwindcss/pull/14750))
- Ensure the JS `theme()` function can reference CSS theme variables that contain special characters without escaping them (e.g. referencing `--width-1\/2` as `theme('width.1/2')`) ([#14739](https://github.com/tailwindlabs/tailwindcss/pull/14739))
- Ensure JS theme keys containing special characters correctly produce utility classes (e.g. `'1/2': 50%` to `w-1/2`) ([#14739](https://github.com/tailwindlabs/tailwindcss/pull/14739))
+- Ensure loading stylesheets via the `?raw` and `?url` static asset query works when using the Vite plugin ([#14716](https://github.com/tailwindlabs/tailwindcss/pull/14716))
- _Upgrade (experimental)_: Migrate `flex-grow` to `grow` and `flex-shrink` to `shrink` ([#14721](https://github.com/tailwindlabs/tailwindcss/pull/14721))
- _Upgrade (experimental)_: Minify arbitrary values when printing candidates ([#14720](https://github.com/tailwindlabs/tailwindcss/pull/14720))
- _Upgrade (experimental)_: Ensure legacy theme values ending in `1` (like `theme(spacing.1)`) are correctly migrated to custom properties ([#14724](https://github.com/tailwindlabs/tailwindcss/pull/14724))
- _Upgrade (experimental)_: Migrate arbitrary values to bare values for the `from-*`, `via-*`, and `to-*` utilities ([#14725](https://github.com/tailwindlabs/tailwindcss/pull/14725))
- _Upgrade (experimental)_: Ensure `layer(utilities)` is removed from `@import` to keep `@utility` top-level ([#14738](https://github.com/tailwindlabs/tailwindcss/pull/14738))
+- _Upgrade (experimental)_: Don't migrate important modifiers that are actually logical negations (e.g. `let foo = !border` to `let foo = border!`) ([#14737](https://github.com/tailwindlabs/tailwindcss/pull/14737))
### Changed
diff --git a/integrations/upgrade/index.test.ts b/integrations/upgrade/index.test.ts
index 80005c088..ceec310ae 100644
--- a/integrations/upgrade/index.test.ts
+++ b/integrations/upgrade/index.test.ts
@@ -26,6 +26,12 @@ test(
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+ @variants hover, focus {
+ .foo {
+ color: red;
+ }
+ }
`,
},
},
@@ -40,6 +46,10 @@ test(
--- ./src/input.css ---
@import 'tailwindcss';
+
+ @utility foo {
+ color: red;
+ }
"
`)
diff --git a/integrations/upgrade/js-config.test.ts b/integrations/upgrade/js-config.test.ts
index cf068b6e6..22e4ace9c 100644
--- a/integrations/upgrade/js-config.test.ts
+++ b/integrations/upgrade/js-config.test.ts
@@ -72,6 +72,11 @@ test(
@tailwind components;
@tailwind utilities;
`,
+ 'src/test.js': ts`
+ export default {
+ shouldNotUse: !border.shouldUse,
+ }
+ `,
'node_modules/my-external-lib/src/template.html': html`
Hello world!
@@ -82,7 +87,7 @@ test(
async ({ exec, fs }) => {
await exec('npx @tailwindcss/upgrade')
- expect(await fs.dumpFiles('src/**/*.css')).toMatchInlineSnapshot(`
+ expect(await fs.dumpFiles('src/**/*.{css,js}')).toMatchInlineSnapshot(`
"
--- src/input.css ---
@import 'tailwindcss';
@@ -134,6 +139,11 @@ test(
}
}
}
+
+ --- src/test.js ---
+ export default {
+ shouldNotUse: !border.shouldUse,
+ }
"
`)
diff --git a/integrations/vite/index.test.ts b/integrations/vite/index.test.ts
index f56575c1a..89814ccc6 100644
--- a/integrations/vite/index.test.ts
+++ b/integrations/vite/index.test.ts
@@ -504,3 +504,64 @@ test(
})
},
)
+
+test(
+ `does not interfere with ?raw and ?url static asset handling`,
+ {
+ fs: {
+ 'package.json': json`
+ {
+ "type": "module",
+ "dependencies": {
+ "@tailwindcss/vite": "workspace:^",
+ "tailwindcss": "workspace:^"
+ },
+ "devDependencies": {
+ "vite": "^5.3.5"
+ }
+ }
+ `,
+ 'vite.config.ts': ts`
+ import tailwindcss from '@tailwindcss/vite'
+ import { defineConfig } from 'vite'
+
+ export default defineConfig({
+ build: { cssMinify: false },
+ plugins: [tailwindcss()],
+ })
+ `,
+ 'index.html': html`
+
+
+
+ `,
+ 'src/index.js': js`
+ import url from './index.css?url'
+ import raw from './index.css?raw'
+ `,
+ 'src/index.css': css`@import 'tailwindcss';`,
+ },
+ },
+ async ({ spawn, getFreePort }) => {
+ let port = await getFreePort()
+ await spawn(`pnpm vite dev --port ${port}`)
+
+ await retryAssertion(async () => {
+ // We have to load the .js file first so that the static assets are
+ // resolved
+ await fetch(`http://localhost:${port}/src/index.js`).then((r) => r.text())
+
+ let [raw, url] = await Promise.all([
+ fetch(`http://localhost:${port}/src/index.css?raw`).then((r) => r.text()),
+ fetch(`http://localhost:${port}/src/index.css?url`).then((r) => r.text()),
+ ])
+
+ expect(firstLine(raw)).toBe(`export default "@import 'tailwindcss';"`)
+ expect(firstLine(url)).toBe(`export default "/src/index.css"`)
+ })
+ },
+)
+
+function firstLine(str: string) {
+ return str.split('\n')[0]
+}
diff --git a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
index 507e72d5f..14a1fc61a 100644
--- a/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
+++ b/packages/@tailwindcss-postcss/src/__snapshots__/index.test.ts.snap
@@ -514,7 +514,7 @@ exports[`\`@import 'tailwindcss'\` is replaced with the generated CSS 1`] = `
}
input:where(:not([type="button"], [type="reset"], [type="submit"])), select, textarea {
- border: 1px solid;
+ border-width: 1px;
}
button, input:where([type="button"], [type="reset"], [type="submit"]) {
diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.test.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.test.ts
index b7370d4d1..d0d231207 100644
--- a/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.test.ts
+++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.test.ts
@@ -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(
diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.ts
index 02bd73dda..538e482c5 100644
--- a/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.ts
+++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-media-screen.ts
@@ -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
diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.test.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.test.ts
index ba2d9ea9d..7c74b1ed6 100644
--- a/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.test.ts
+++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.test.ts
@@ -400,3 +400,19 @@ it('should drop `@tailwind variants;`', async () => {
`),
).toEqual('')
})
+
+it('should replace `@responsive` with its children', async () => {
+ expect(
+ await migrate(css`
+ @responsive {
+ .foo {
+ color: red;
+ }
+ }
+ `),
+ ).toMatchInlineSnapshot(`
+ ".foo {
+ color: red;
+ }"
+ `)
+})
diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.ts
index 0f7143017..d3d74a65e 100644
--- a/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.ts
+++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-tailwind-directives.ts
@@ -54,6 +54,18 @@ export function migrateTailwindDirectives(options: { newPrefix: string | null })
) {
node.remove()
}
+
+ // Replace Tailwind CSS v2 directives that still worked in v3.
+ else if (node.name === 'responsive') {
+ if (node.nodes) {
+ for (let child of node.nodes) {
+ child.raws.tailwind_pretty = true
+ }
+ node.replaceWith(node.nodes)
+ } else {
+ node.remove()
+ }
+ }
})
// Insert default import if all directives are present
diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-variants-directive.test.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-variants-directive.test.ts
new file mode 100644
index 000000000..e18a161e6
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-variants-directive.test.ts
@@ -0,0 +1,33 @@
+import dedent from 'dedent'
+import postcss from 'postcss'
+import { expect, it } from 'vitest'
+import { formatNodes } from './format-nodes'
+import { migrateVariantsDirective } from './migrate-variants-directive'
+
+const css = dedent
+
+function migrate(input: string) {
+ return postcss()
+ .use(migrateVariantsDirective())
+ .use(formatNodes())
+ .process(input, { from: expect.getState().testPath })
+ .then((result) => result.css)
+}
+
+it('should replace `@variants` with `@layer utilities`', async () => {
+ expect(
+ await migrate(css`
+ @variants hover, focus {
+ .foo {
+ color: red;
+ }
+ }
+ `),
+ ).toMatchInlineSnapshot(`
+ "@layer utilities {
+ .foo {
+ color: red;
+ }
+ }"
+ `)
+})
diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-variants-directive.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-variants-directive.ts
new file mode 100644
index 000000000..1592c0059
--- /dev/null
+++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-variants-directive.ts
@@ -0,0 +1,35 @@
+import { type Plugin, type Root } from 'postcss'
+
+export function migrateVariantsDirective(): Plugin {
+ function migrate(root: Root) {
+ root.walkAtRules('variants', (node) => {
+ // Migrate `@variants` to `@utility` because `@variants` make the classes
+ // an actual utility.
+ // ```css
+ // @variants hover {
+ // .foo {}
+ // }
+ // ```
+ //
+ // Means that you can do this in your HTML:
+ // ```html
+ //
+ // ```
+ //
+ // Notice the `focus:`, even though we _only_ configured the `hover`
+ // variant.
+ //
+ // This means that we can convert it to an `@layer utilities` rule. Later,
+ // this will get converted to an `@utility` rule.
+ if (node.name === 'variants') {
+ node.name = 'layer'
+ node.params = 'utilities'
+ }
+ })
+ }
+
+ return {
+ postcssPlugin: '@tailwindcss/upgrade/migrate-variants-directive',
+ OnceExit: migrate,
+ }
+}
diff --git a/packages/@tailwindcss-upgrade/src/migrate.ts b/packages/@tailwindcss-upgrade/src/migrate.ts
index 1b72afc6f..4220904c9 100644
--- a/packages/@tailwindcss-upgrade/src/migrate.ts
+++ b/packages/@tailwindcss-upgrade/src/migrate.ts
@@ -11,6 +11,7 @@ import { migrateMediaScreen } from './codemods/migrate-media-screen'
import { migrateMissingLayers } from './codemods/migrate-missing-layers'
import { migrateTailwindDirectives } from './codemods/migrate-tailwind-directives'
import { migrateThemeToVar } from './codemods/migrate-theme-to-var'
+import { migrateVariantsDirective } from './codemods/migrate-variants-directive'
import type { JSConfigMigration } from './migrate-js-config'
import { Stylesheet, type StylesheetConnection, type StylesheetId } from './stylesheet'
import { resolveCssId } from './utils/resolve'
@@ -38,6 +39,7 @@ export async function migrateContents(
.use(migrateAtApply(options))
.use(migrateThemeToVar(options))
.use(migrateMediaScreen(options))
+ .use(migrateVariantsDirective())
.use(migrateAtLayerUtilities(stylesheet))
.use(migrateMissingLayers())
.use(migrateTailwindDirectives(options))
diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/important.test.ts b/packages/@tailwindcss-upgrade/src/template/codemods/important.test.ts
index 4a53f8d4a..64f098b9b 100644
--- a/packages/@tailwindcss-upgrade/src/template/codemods/important.test.ts
+++ b/packages/@tailwindcss-upgrade/src/template/codemods/important.test.ts
@@ -15,5 +15,39 @@ test.each([
base: __dirname,
})
- expect(important(designSystem, {}, candidate)).toEqual(result)
+ expect(
+ important(designSystem, {}, candidate, {
+ contents: `"${candidate}"`,
+ start: 1,
+ end: candidate.length + 1,
+ }),
+ ).toEqual(result)
+})
+
+test('does not match false positives', async () => {
+ let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss";', {
+ base: __dirname,
+ })
+
+ expect(
+ important(designSystem, {}, '!border', {
+ contents: `let notBorder = !border\n`,
+ start: 16,
+ end: 16 + '!border'.length,
+ }),
+ ).toEqual('!border')
+})
+
+test('does not match false positives with spaces at the end of the line', async () => {
+ let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss";', {
+ base: __dirname,
+ })
+
+ expect(
+ important(designSystem, {}, '!border', {
+ contents: `let notBorder = !border \n`,
+ start: 16,
+ end: 16 + '!border'.length,
+ }),
+ ).toEqual('!border')
})
diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/important.ts b/packages/@tailwindcss-upgrade/src/template/codemods/important.ts
index 69dbdba85..454790529 100644
--- a/packages/@tailwindcss-upgrade/src/template/codemods/important.ts
+++ b/packages/@tailwindcss-upgrade/src/template/codemods/important.ts
@@ -19,9 +19,50 @@ export function important(
designSystem: DesignSystem,
_userConfig: Config,
rawCandidate: string,
+ location?: {
+ contents: string
+ start: number
+ end: number
+ },
): string {
for (let candidate of parseCandidate(rawCandidate, designSystem)) {
if (candidate.important && candidate.raw[candidate.raw.length - 1] !== '!') {
+ // The important migration is one of the most broad migrations with a high
+ // potential of matching false positives since `!` is a valid character in
+ // most programming languages. Since v4 is technically backward compatible
+ // with v3 in that it can read `!` in the front of the utility too, we err
+ // on the side of caution and only migrate candidates that we are certain
+ // are inside of a string.
+ if (location) {
+ let isQuoteBeforeCandidate = false
+ for (let i = location.start - 1; i >= 0; i--) {
+ let char = location.contents.at(i)!
+ if (char === '\n') {
+ break
+ }
+ if (isQuote(char)) {
+ isQuoteBeforeCandidate = true
+ break
+ }
+ }
+
+ let isQuoteAfterCandidate = false
+ for (let i = location.end; i < location.contents.length; i++) {
+ let char = location.contents.at(i)!
+ if (char === '\n') {
+ break
+ }
+ if (isQuote(char)) {
+ isQuoteAfterCandidate = true
+ break
+ }
+ }
+
+ if (!isQuoteBeforeCandidate || !isQuoteAfterCandidate) {
+ continue
+ }
+ }
+
// The printCandidate function will already put the exclamation mark in
// the right place, so we just need to mark this candidate as requiring a
// migration.
@@ -31,3 +72,14 @@ export function important(
return rawCandidate
}
+
+function isQuote(char: string) {
+ switch (char) {
+ case '"':
+ case "'":
+ case '`':
+ return true
+ default:
+ return false
+ }
+}
diff --git a/packages/@tailwindcss-upgrade/src/template/migrate.ts b/packages/@tailwindcss-upgrade/src/template/migrate.ts
index c6aa0a11c..5e2d02eab 100644
--- a/packages/@tailwindcss-upgrade/src/template/migrate.ts
+++ b/packages/@tailwindcss-upgrade/src/template/migrate.ts
@@ -17,6 +17,11 @@ export type Migration = (
designSystem: DesignSystem,
userConfig: Config,
rawCandidate: string,
+ location?: {
+ contents: string
+ start: number
+ end: number
+ },
) => string
export const DEFAULT_MIGRATIONS: Migration[] = [
@@ -34,9 +39,15 @@ export function migrateCandidate(
designSystem: DesignSystem,
userConfig: Config,
rawCandidate: string,
+ // Location is only set when migrating a candidate from a source file
+ location?: {
+ contents: string
+ start: number
+ end: number
+ },
): string {
for (let migration of DEFAULT_MIGRATIONS) {
- rawCandidate = migration(designSystem, userConfig, rawCandidate)
+ rawCandidate = migration(designSystem, userConfig, rawCandidate, location)
}
return rawCandidate
}
@@ -52,7 +63,11 @@ export default async function migrateContents(
let changes: StringChange[] = []
for (let { rawCandidate, start, end } of candidates) {
- let migratedCandidate = migrateCandidate(designSystem, userConfig, rawCandidate)
+ let migratedCandidate = migrateCandidate(designSystem, userConfig, rawCandidate, {
+ contents,
+ start,
+ end,
+ })
if (migratedCandidate === rawCandidate) {
continue
diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts
index abb13a613..9571342cd 100644
--- a/packages/@tailwindcss-vite/src/index.ts
+++ b/packages/@tailwindcss-vite/src/index.ts
@@ -5,6 +5,8 @@ import { Features, transform } from 'lightningcss'
import path from 'path'
import type { Plugin, ResolvedConfig, Rollup, Update, ViteDevServer } from 'vite'
+const SPECIAL_QUERY_RE = /[?&](raw|url)\b/
+
export default function tailwindcss(): Plugin[] {
let servers: ViteDevServer[] = []
let config: ResolvedConfig | null = null
@@ -261,9 +263,12 @@ function getExtension(id: string) {
function isPotentialCssRootFile(id: string) {
let extension = getExtension(id)
let isCssFile =
- extension === 'css' ||
- (extension === 'vue' && id.includes('&lang.css')) ||
- (extension === 'astro' && id.includes('&lang.css'))
+ (extension === 'css' ||
+ (extension === 'vue' && id.includes('&lang.css')) ||
+ (extension === 'astro' && id.includes('&lang.css'))) &&
+ // Don't intercept special static asset resources
+ !SPECIAL_QUERY_RE.test(id)
+
return isCssFile
}
diff --git a/packages/tailwindcss/preflight.css b/packages/tailwindcss/preflight.css
index c1857b1bf..6e57b9faa 100644
--- a/packages/tailwindcss/preflight.css
+++ b/packages/tailwindcss/preflight.css
@@ -200,7 +200,7 @@ textarea,
input:where(:not([type='button'], [type='reset'], [type='submit'])),
select,
textarea {
- border: 1px solid;
+ border-width: 1px;
}
/*
diff --git a/playgrounds/vite/package.json b/playgrounds/vite/package.json
index 846b96252..a5a953a14 100644
--- a/playgrounds/vite/package.json
+++ b/playgrounds/vite/package.json
@@ -19,7 +19,6 @@
"@types/react": "^18.3.9",
"@types/react-dom": "^18.3.1",
"bun": "^1.1.29",
- "vite": "catalog:",
- "vite-plugin-handlebars": "^2.0.0"
+ "vite": "catalog:"
}
}
diff --git a/playgrounds/vite/src/animate.js b/playgrounds/vite/src/animate.js
deleted file mode 100644
index 0a5617399..000000000
--- a/playgrounds/vite/src/animate.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('tailwindcss-animate')
diff --git a/playgrounds/vite/src/app.tsx b/playgrounds/vite/src/app.tsx
index 285bd4143..8ec502989 100644
--- a/playgrounds/vite/src/app.tsx
+++ b/playgrounds/vite/src/app.tsx
@@ -1,11 +1,7 @@
-import { Foo } from './foo'
-
export function App() {
return (
Hello World
-
-
)
}
diff --git a/playgrounds/vite/src/bar.tsx b/playgrounds/vite/src/bar.tsx
deleted file mode 100644
index 1efa2c004..000000000
--- a/playgrounds/vite/src/bar.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-export function Bar() {
- return (
-
-
Bar
-
- )
-}
diff --git a/playgrounds/vite/src/foo.tsx b/playgrounds/vite/src/foo.tsx
deleted file mode 100644
index 60ec68b55..000000000
--- a/playgrounds/vite/src/foo.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Bar } from './bar'
-
-export function Foo() {
- return (
-
-
Foo
-
-
- )
-}
diff --git a/playgrounds/vite/src/forms.js b/playgrounds/vite/src/forms.js
deleted file mode 100644
index f288ddfa0..000000000
--- a/playgrounds/vite/src/forms.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('@tailwindcss/forms')
diff --git a/playgrounds/vite/src/app.css b/playgrounds/vite/src/index.css
similarity index 50%
rename from playgrounds/vite/src/app.css
rename to playgrounds/vite/src/index.css
index adbd8e19f..d4b507858 100644
--- a/playgrounds/vite/src/app.css
+++ b/playgrounds/vite/src/index.css
@@ -1,2 +1 @@
@import 'tailwindcss';
-@plugin "./plugin.js";
diff --git a/playgrounds/vite/src/index.html b/playgrounds/vite/src/index.html
index d4b60a84a..858e0cf2f 100644
--- a/playgrounds/vite/src/index.html
+++ b/playgrounds/vite/src/index.html
@@ -4,7 +4,6 @@
≈ Playground
-
diff --git a/playgrounds/vite/src/main.tsx b/playgrounds/vite/src/main.tsx
index b8df681f3..6b81fa915 100644
--- a/playgrounds/vite/src/main.tsx
+++ b/playgrounds/vite/src/main.tsx
@@ -2,6 +2,8 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import { App } from './app'
+import './index.css'
+
ReactDOM.createRoot(document.getElementById('app')!).render(
diff --git a/playgrounds/vite/src/plugin.js b/playgrounds/vite/src/plugin.js
deleted file mode 100644
index 085212671..000000000
--- a/playgrounds/vite/src/plugin.js
+++ /dev/null
@@ -1,4 +0,0 @@
-module.exports = function ({ addVariant }) {
- addVariant('inverted', '@media (inverted-colors: inverted)')
- addVariant('hocus', ['&:focus', '&:hover'])
-}
diff --git a/playgrounds/vite/src/typography.js b/playgrounds/vite/src/typography.js
deleted file mode 100644
index 711af27f7..000000000
--- a/playgrounds/vite/src/typography.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('@tailwindcss/typography')
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a13e85711..ba225832c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -435,9 +435,6 @@ importers:
vite:
specifier: 'catalog:'
version: 5.4.0(@types/node@20.14.13)(lightningcss@1.26.0(patch_hash=5hwfyehqvg5wjb7mwtdvubqbl4))(terser@5.31.6)
- vite-plugin-handlebars:
- specifier: ^2.0.0
- version: 2.0.0(@types/node@20.14.13)(lightningcss@1.26.0(patch_hash=5hwfyehqvg5wjb7mwtdvubqbl4))(terser@5.31.6)
packages:
@@ -1941,11 +1938,6 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- handlebars@4.7.8:
- resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==}
- engines: {node: '>=0.4.7'}
- hasBin: true
-
has-bigints@1.0.2:
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
@@ -2352,9 +2344,6 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
- neo-async@2.6.2:
- resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
-
next@14.1.0:
resolution: {integrity: sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==}
engines: {node: '>=18.17.0'}
@@ -3007,11 +2996,6 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
- uglify-js@3.19.1:
- resolution: {integrity: sha512-y/2wiW+ceTYR2TSSptAhfnEtpLaQ4Ups5zrjB2d3kuVxHj16j/QJwPl5PvuGy9uARb39J0+iKxcRPvtpsx4A4A==}
- engines: {node: '>=0.8.0'}
- hasBin: true
-
unbox-primitive@1.0.2:
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
@@ -3039,9 +3023,6 @@ packages:
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
- vite-plugin-handlebars@2.0.0:
- resolution: {integrity: sha512-+J3It0nyhPzx4nT1I+fnWH+jShTEXzm6X0Tgsggdm9IYFD7/eJ6a3ROI13HTe0CVoyaxm/fPxH5HDAKyfz7T0g==}
-
vite@5.4.0:
resolution: {integrity: sha512-5xokfMX0PIiwCMCMb9ZJcMyh5wbBun0zUzKib+L65vAZ8GY9ePZMXxFrHbr/Kyll2+LSCY7xtERPpxkBDKngwg==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -3133,9 +3114,6 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
- wordwrap@1.0.0:
- resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
-
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -4739,15 +4717,6 @@ snapshots:
graceful-fs@4.2.11: {}
- handlebars@4.7.8:
- dependencies:
- minimist: 1.2.8
- neo-async: 2.6.2
- source-map: 0.6.1
- wordwrap: 1.0.0
- optionalDependencies:
- uglify-js: 3.19.1
-
has-bigints@1.0.2: {}
has-flag@3.0.0: {}
@@ -5088,8 +5057,6 @@ snapshots:
natural-compare@1.4.0: {}
- neo-async@2.6.2: {}
-
next@14.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
dependencies:
'@next/env': 14.1.0
@@ -5486,7 +5453,8 @@ snapshots:
source-map: 0.6.1
optional: true
- source-map@0.6.1: {}
+ source-map@0.6.1:
+ optional: true
source-map@0.8.0-beta.0:
dependencies:
@@ -5761,9 +5729,6 @@ snapshots:
typescript@5.5.4: {}
- uglify-js@3.19.1:
- optional: true
-
unbox-primitive@1.0.2:
dependencies:
call-bind: 1.0.7
@@ -5805,20 +5770,6 @@ snapshots:
- supports-color
- terser
- vite-plugin-handlebars@2.0.0(@types/node@20.14.13)(lightningcss@1.26.0(patch_hash=5hwfyehqvg5wjb7mwtdvubqbl4))(terser@5.31.6):
- dependencies:
- handlebars: 4.7.8
- vite: 5.4.0(@types/node@20.14.13)(lightningcss@1.26.0(patch_hash=5hwfyehqvg5wjb7mwtdvubqbl4))(terser@5.31.6)
- transitivePeerDependencies:
- - '@types/node'
- - less
- - lightningcss
- - sass
- - sass-embedded
- - stylus
- - sugarss
- - terser
-
vite@5.4.0(@types/node@20.14.13)(lightningcss@1.26.0(patch_hash=5hwfyehqvg5wjb7mwtdvubqbl4))(terser@5.31.6):
dependencies:
esbuild: 0.21.5
@@ -5920,8 +5871,6 @@ snapshots:
word-wrap@1.2.5: {}
- wordwrap@1.0.0: {}
-
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0