diff --git a/.changeset/large-timers-kneel.md b/.changeset/large-timers-kneel.md new file mode 100644 index 000000000..b49b194ac --- /dev/null +++ b/.changeset/large-timers-kneel.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +replace tailwindcss-animate with tw-animate-css diff --git a/apps/v4/app/favicon.ico b/apps/v4/app/favicon.ico deleted file mode 100644 index 718d6fea4..000000000 Binary files a/apps/v4/app/favicon.ico and /dev/null differ diff --git a/apps/v4/app/globals.css b/apps/v4/app/globals.css index c7ee6a88c..53a84b314 100644 --- a/apps/v4/app/globals.css +++ b/apps/v4/app/globals.css @@ -111,26 +111,6 @@ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); - --animate-accordion-down: accordion-down 0.2s ease-out; - --animate-accordion-up: accordion-up 0.2s ease-out; - - @keyframes accordion-down { - from { - height: 0; - } - to { - height: var(--radix-accordion-content-height); - } - } - - @keyframes accordion-up { - from { - height: var(--radix-accordion-content-height); - } - to { - height: 0; - } - } } @layer base { diff --git a/apps/v4/package.json b/apps/v4/package.json index 34746ba2f..cf37158ef 100644 --- a/apps/v4/package.json +++ b/apps/v4/package.json @@ -77,9 +77,8 @@ "sonner": "^2.0.0", "tailwind-merge": "^3.0.1", "tailwindcss": "^4.0.7", - "tailwindcss-animate": "^1.0.7", "ts-morph": "^22.0.0", - "tw-animate-css": "^1.2.2", + "tw-animate-css": "^1.2.4", "vaul": "1.1.2", "zod": "^3.24.1" }, diff --git a/apps/v4/registry.json b/apps/v4/registry.json index 3a094cc01..e3485993a 100644 --- a/apps/v4/registry.json +++ b/apps/v4/registry.json @@ -6,7 +6,7 @@ "name": "index", "type": "registry:style", "dependencies": [ - "tailwindcss-animate", + "tw-animate-css", "class-variance-authority", "lucide-react" ], @@ -14,13 +14,6 @@ "utils" ], "files": [], - "tailwind": { - "config": { - "plugins": [ - "require(\"tailwindcss-animate\")" - ] - } - }, "cssVars": {} }, { diff --git a/apps/v4/scripts/build-registry.mts b/apps/v4/scripts/build-registry.mts index 7eeb8ed6a..e583049d6 100644 --- a/apps/v4/scripts/build-registry.mts +++ b/apps/v4/scripts/build-registry.mts @@ -21,16 +21,11 @@ const registry = { name: "index", type: "registry:style", dependencies: [ - "tailwindcss-animate", + "tw-animate-css", "class-variance-authority", "lucide-react", ], registryDependencies: ["utils"], - tailwind: { - config: { - plugins: [`require("tailwindcss-animate")`], - }, - }, cssVars: {}, files: [], }, diff --git a/apps/www/content/docs/installation/manual.mdx b/apps/www/content/docs/installation/manual.mdx index 255ee9c36..ad775bdb8 100644 --- a/apps/www/content/docs/installation/manual.mdx +++ b/apps/www/content/docs/installation/manual.mdx @@ -16,7 +16,7 @@ Components are styled using Tailwind CSS. You need to install Tailwind CSS in yo Add the following dependencies to your project: ```bash -npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react +npm install class-variance-authority clsx tailwind-merge lucide-react tw-animate-css ``` ### Configure path aliases @@ -42,8 +42,7 @@ Add the following to your styles/globals.css file. You can learn more about usin ```css showLineNumbers title="src/styles/globals.css" @import "tailwindcss"; - -@plugin 'tailwindcss-animate'; +@import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); diff --git a/apps/www/public/r/styles/new-york-v4/index.json b/apps/www/public/r/styles/new-york-v4/index.json index a9ef59549..8e85cbd88 100644 --- a/apps/www/public/r/styles/new-york-v4/index.json +++ b/apps/www/public/r/styles/new-york-v4/index.json @@ -3,7 +3,7 @@ "name": "index", "type": "registry:style", "dependencies": [ - "tailwindcss-animate", + "tw-animate-css", "class-variance-authority", "lucide-react" ], @@ -11,12 +11,5 @@ "utils" ], "files": [], - "tailwind": { - "config": { - "plugins": [ - "require(\"tailwindcss-animate\")" - ] - } - }, "cssVars": {} } \ No newline at end of file diff --git a/packages/shadcn/src/utils/updaters/update-css-vars.ts b/packages/shadcn/src/utils/updaters/update-css-vars.ts index c68ee2b0e..0dfacca65 100644 --- a/packages/shadcn/src/utils/updaters/update-css-vars.ts +++ b/packages/shadcn/src/utils/updaters/update-css-vars.ts @@ -83,7 +83,10 @@ export async function transformCssVars( } if (options.tailwindVersion === "v4") { - plugins = [addCustomVariant({ params: "dark (&:is(.dark *))" })] + plugins = [ + addCustomImport({ params: "tw-animate-css" }), + addCustomVariant({ params: "dark (&:is(.dark *))" }), + ] if (options.cleanupDefaultNextStyles) { plugins.push(cleanupDefaultNextStylesPlugin()) @@ -543,19 +546,83 @@ function addCustomVariant({ params }: { params: string }) { (node): node is AtRule => node.type === "atrule" && node.name === "custom-variant" ) + if (!customVariant) { + // Find all import nodes + const importNodes = root.nodes.filter( + (node): node is AtRule => + node.type === "atrule" && node.name === "import" + ) + const variantNode = postcss.atRule({ name: "custom-variant", params, raws: { semicolon: true, before: "\n" }, }) - root.insertAfter(root.nodes[0], variantNode) + + if (importNodes.length > 0) { + // Insert after the last import + const lastImport = importNodes[importNodes.length - 1] + root.insertAfter(lastImport, variantNode) + } else { + // If no imports, insert after the first node + root.insertAfter(root.nodes[0], variantNode) + } + root.insertBefore(variantNode, postcss.comment({ text: "---break---" })) } }, } } +function addCustomImport({ params }: { params: string }) { + return { + postcssPlugin: "add-custom-import", + Once(root: Root) { + const importNodes = root.nodes.filter( + (node): node is AtRule => + node.type === "atrule" && node.name === "import" + ) + + // Find custom variant node (to ensure we insert before it) + const customVariantNode = root.nodes.find( + (node): node is AtRule => + node.type === "atrule" && node.name === "custom-variant" + ) + + // Check if our specific import already exists + const hasImport = importNodes.some( + (node) => node.params.replace(/["']/g, "") === params + ) + + if (!hasImport) { + const importNode = postcss.atRule({ + name: "import", + params: `"${params}"`, + raws: { semicolon: true, before: "\n" }, + }) + + if (importNodes.length > 0) { + // If there are existing imports, add after the last import + const lastImport = importNodes[importNodes.length - 1] + root.insertAfter(lastImport, importNode) + } else if (customVariantNode) { + // If no imports but has custom-variant, insert before it + root.insertBefore(customVariantNode, importNode) + root.insertBefore( + customVariantNode, + postcss.comment({ text: "---break---" }) + ) + } else { + // If no imports and no custom-variant, insert at the start + root.prepend(importNode) + root.insertAfter(importNode, postcss.comment({ text: "---break---" })) + } + } + }, + } +} + function updateTailwindConfigPlugin( tailwindConfig: z.infer["config"] ) { diff --git a/packages/shadcn/test/utils/updaters/update-css-vars.test.ts b/packages/shadcn/test/utils/updaters/update-css-vars.test.ts index 534c07f89..09adadd7c 100644 --- a/packages/shadcn/test/utils/updaters/update-css-vars.test.ts +++ b/packages/shadcn/test/utils/updaters/update-css-vars.test.ts @@ -202,6 +202,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -260,6 +261,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); :root { @@ -324,6 +326,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); :root { @@ -389,6 +392,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); :root { @@ -464,6 +468,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); :root { @@ -525,6 +530,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -575,6 +581,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -625,6 +632,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -673,6 +681,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -728,6 +737,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); :root { --radius: 0.125rem; @@ -769,6 +779,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -812,6 +823,7 @@ describe("transformCssVarsV4", () => { "@import "tailwindcss"; @plugin "tailwindcss-animate"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -847,6 +859,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @plugin "tailwindcss-animate"; @@ -888,6 +901,7 @@ describe("transformCssVarsV4", () => { @plugin '@tailwindcss/typography'; @plugin 'tailwindcss-animate'; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -932,6 +946,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -1008,6 +1023,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -1076,6 +1092,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -1150,6 +1167,7 @@ describe("transformCssVarsV4", () => { ) ).toMatchInlineSnapshot(` "@import "tailwindcss"; + @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @theme inline { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4cdb94505..6e89fb250 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -294,15 +294,12 @@ importers: tailwindcss: specifier: ^4.0.7 version: 4.0.7 - tailwindcss-animate: - specifier: ^1.0.7 - version: 1.0.7(tailwindcss@4.0.7) ts-morph: specifier: ^22.0.0 version: 22.0.0 tw-animate-css: - specifier: ^1.2.2 - version: 1.2.2 + specifier: ^1.2.4 + version: 1.2.4 vaul: specifier: 1.1.2 version: 1.1.2(@types/react-dom@19.0.3(@types/react@19.0.8))(@types/react@19.0.8)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -7767,8 +7764,8 @@ packages: resolution: {integrity: sha512-1q7+9UJABuBAHrcC4Sxp5lOqYS5mvxRrwa33wpIyM18hlOCpRD/fTJNxZ0vhbMcJmz15o9kkVm743mPn7p6jpQ==} hasBin: true - tw-animate-css@1.2.2: - resolution: {integrity: sha512-TdSaQcV+V8MypECoXr6Nnv3EQFz05kxfTUaOHtpWTQZp8r5Bx2OmTnkSZVlOTaRiS20a6wYw0RaAnNX2D8ywrQ==} + tw-animate-css@1.2.4: + resolution: {integrity: sha512-yt+HkJB41NAvOffe4NweJU6fLqAlVx/mBX6XmHRp15kq0JxTtOKaIw8pVSWM1Z+n2nXtyi7cW6C9f0WG/F/QAQ==} typanion@3.14.0: resolution: {integrity: sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==} @@ -17231,10 +17228,6 @@ snapshots: dependencies: tailwindcss: 3.4.6(ts-node@10.9.2(@types/node@20.17.16)(typescript@5.7.3)) - tailwindcss-animate@1.0.7(tailwindcss@4.0.7): - dependencies: - tailwindcss: 4.0.7 - tailwindcss@3.4.6(ts-node@10.9.2(@types/node@17.0.45)(typescript@5.7.3)): dependencies: '@alloc/quick-lru': 5.2.0 @@ -17619,7 +17612,7 @@ snapshots: turbo-windows-64: 1.13.4 turbo-windows-arm64: 1.13.4 - tw-animate-css@1.2.2: {} + tw-animate-css@1.2.4: {} typanion@3.14.0: {} diff --git a/templates/monorepo-next/packages/ui/package.json b/templates/monorepo-next/packages/ui/package.json index c9f050abb..61627fb3c 100644 --- a/templates/monorepo-next/packages/ui/package.json +++ b/templates/monorepo-next/packages/ui/package.json @@ -15,7 +15,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "tailwind-merge": "^3.0.1", - "tailwindcss-animate": "^1.0.7", + "tw-animate-css": "^1.2.4", "zod": "^3.24.2" }, "devDependencies": { diff --git a/templates/monorepo-next/packages/ui/src/styles/globals.css b/templates/monorepo-next/packages/ui/src/styles/globals.css index c04e5d9ea..a5c6ce38a 100644 --- a/templates/monorepo-next/packages/ui/src/styles/globals.css +++ b/templates/monorepo-next/packages/ui/src/styles/globals.css @@ -3,7 +3,7 @@ @source "../../../components/**/*.{ts,tsx}"; @source "../**/*.{ts,tsx}"; -@plugin "tailwindcss-animate"; +@import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @@ -115,26 +115,6 @@ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-border: var(--sidebar-border); --color-sidebar-ring: var(--sidebar-ring); - --animate-accordion-down: accordion-down 0.2s ease-out; - --animate-accordion-up: accordion-up 0.2s ease-out; - - @keyframes accordion-down { - from { - height: 0; - } - to { - height: var(--radix-accordion-content-height); - } - } - - @keyframes accordion-up { - from { - height: var(--radix-accordion-content-height); - } - to { - height: 0; - } - } } @layer base { diff --git a/templates/monorepo-next/pnpm-lock.yaml b/templates/monorepo-next/pnpm-lock.yaml index dcf4474f1..894a3c133 100644 --- a/templates/monorepo-next/pnpm-lock.yaml +++ b/templates/monorepo-next/pnpm-lock.yaml @@ -131,9 +131,9 @@ importers: tailwind-merge: specifier: ^3.0.1 version: 3.0.1 - tailwindcss-animate: - specifier: ^1.0.7 - version: 1.0.7(tailwindcss@4.0.8) + tw-animate-css: + specifier: ^1.2.4 + version: 1.2.4 zod: specifier: ^3.24.2 version: 3.24.2 @@ -2106,11 +2106,6 @@ packages: tailwind-merge@3.0.1: resolution: {integrity: sha512-AvzE8FmSoXC7nC+oU5GlQJbip2UO7tmOhOfQyOmPhrStOGXHU08j8mZEHZ4BmCqY5dWTCo4ClWkNyRNx1wpT0g==} - tailwindcss-animate@1.0.7: - resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} - peerDependencies: - tailwindcss: '>=3.0.0 || insiders' - tailwindcss@4.0.8: resolution: {integrity: sha512-Me7N5CKR+D2A1xdWA5t5+kjjT7bwnxZOE6/yDI/ixJdJokszsn2n++mdU5yJwrsTpqFX2B9ZNMBJDwcqk9C9lw==} @@ -2198,6 +2193,9 @@ packages: resolution: {integrity: sha512-Qxi0ioQCxMRUCcHKHZkTnYH8e7XCpNfg9QiJcyfWIc+ZXeaCjzV5rCGlbQlTXMAtI8qgfP8fZADv3CFtPwqdPQ==} hasBin: true + tw-animate-css@1.2.4: + resolution: {integrity: sha512-yt+HkJB41NAvOffe4NweJU6fLqAlVx/mBX6XmHRp15kq0JxTtOKaIw8pVSWM1Z+n2nXtyi7cW6C9f0WG/F/QAQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -4522,10 +4520,6 @@ snapshots: tailwind-merge@3.0.1: {} - tailwindcss-animate@1.0.7(tailwindcss@4.0.8): - dependencies: - tailwindcss: 4.0.8 - tailwindcss@4.0.8: {} tapable@2.2.1: {} @@ -4605,6 +4599,8 @@ snapshots: turbo-windows-64: 2.4.2 turbo-windows-arm64: 2.4.2 + tw-animate-css@1.2.4: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1