diff --git a/CHANGELOG.md b/CHANGELOG.md index 377ef036230a..f97dc1f72470 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix class extraction followed by `(` in Pug ([#17320](https://github.com/tailwindlabs/tailwindcss/pull/17320)) +- Ensure `@keyframes` for theme animations are emitted if they are referenced following a comma - Vite: Ensure that updates to an imported CSS file are properly propagated after updating templates ([#17347](https://github.com/tailwindlabs/tailwindcss/pull/17347)) - Pre process `Slim` templates embedded in Ruby files ([#17336](https://github.com/tailwindlabs/tailwindcss/pull/17336)) - Error when input and output files resolve to the same file when using the CLI ([#17311](https://github.com/tailwindlabs/tailwindcss/pull/17311)) diff --git a/packages/tailwindcss/src/ast.ts b/packages/tailwindcss/src/ast.ts index 83674d1148e9..e13e19743209 100644 --- a/packages/tailwindcss/src/ast.ts +++ b/packages/tailwindcss/src/ast.ts @@ -310,8 +310,8 @@ export function optimizeAst(ast: AstNode[], designSystem: DesignSystem) { // Track used animation names if (node.property === 'animation') { - let parts = node.value.split(/\s+/) - for (let part of parts) usedKeyframeNames.add(part) + for (let keyframeName of extractKeyframeNames(node.value)) + usedKeyframeNames.add(keyframeName) } parent.push(node) @@ -438,8 +438,8 @@ export function optimizeAst(ast: AstNode[], designSystem: DesignSystem) { ) if (variableUsed) { if (declaration.property.startsWith(designSystem.theme.prefixKey('--animate-'))) { - let parts = declaration.value!.split(/\s+/) - for (let part of parts) usedKeyframeNames.add(part) + for (let keyframeName of extractKeyframeNames(declaration.value!)) + usedKeyframeNames.add(keyframeName) } continue @@ -605,3 +605,7 @@ function isVariableUsed( return false } + +function extractKeyframeNames(value: string): string[] { + return value.split(/[\s,]+/) +} diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index ce3dd9d47182..25d30f2ea670 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -1939,6 +1939,49 @@ describe('Parsing theme values from CSS', () => { `) }) + // https://github.com/tailwindlabs/tailwindcss/issues/17332 + test('extracts keyframe names followed by comma', async () => { + expect( + await compileCss( + css` + @theme { + --animate-test: 500ms both fade-in, 1000ms linear 500ms spin infinite; + + @keyframes fade-in { + from { + opacity: 0%; + } + to { + opacity: 100%; + } + } + } + + @tailwind utilities; + `, + ['animate-test'], + ), + ).toMatchInlineSnapshot(` + ":root, :host { + --animate-test: .5s both fade-in, 1s linear .5s spin infinite; + } + + .animate-test { + animation: var(--animate-test); + } + + @keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } + }" + `) + }) + test('keyframes outside of `@theme are always preserved', async () => { expect( await compileCss(