Skip to content

[codemod] Support keyframes in jss-to-styled - #49119

Open
stop1love1 wants to merge 1 commit into
mui:masterfrom
stop1love1:fix/codemod-jss-to-styled-keyframes
Open

stop1love1 wants to merge 1 commit into
mui:masterfrom
stop1love1:fix/codemod-jss-to-styled-keyframes

Conversation

@stop1love1

Copy link
Copy Markdown

Closes #30801

Problem

v5.0.0/jss-to-styled throws on any style object that declares keyframes, and since the transform aborts, nothing in the file is migrated:

Error: undefined does not match field "name": string of type Identifier
  at createClasses (src/v5.0.0/jss-to-styled.js:179)
const useStyles = makeStyles((theme) => ({
  root: { animation: '$pulse 1.5s ease-in-out infinite' },
  '@keyframes pulse': { '0%': { opacity: 1 }, '100%': { opacity: 0.4 } },
}));

createClasses walks every entry of the style object and reads prop.key.name, assuming each one is a class name written as an identifier. JSS declares keyframes with a string key, so prop.key.name is undefined, and j.identifier(undefined) throws.

This matches what was established in the issue thread — @mnajdova asked whether keyframes were supported and @siriwatknp confirmed "the Codemod does not transform the keyframes at this point".

Solution

A keyframes entry is not a class, and — unlike @media — the keys it nests (0%, from, to) are not class names either. So the whole property is carried over untouched, which is exactly what emotion expects in an object style. It is skipped in the three places that build class names: the classes map, the & .${classes.x} selector rewrite, and the withStyles classes mapping.

One more step is needed for the output to actually work: JSS references a keyframe as $pulse, emotion by its bare name. The $ is dropped, but only for names that the same style object really declares via @keyframes, so unrelated strings are left alone.

-const useStyles = makeStyles((theme) => ({
-  root: {
-    animation: '$pulse 1.5s ease-in-out infinite',
+const Root = styled('div')(({ theme }) => ({
+  [`&.${classes.root}`]: {
+    animation: 'pulse 1.5s ease-in-out infinite',
     color: theme.palette.primary.main,
   },
   '@keyframes pulse': { … },
 }));

Deliberately out of scope

Other at-rules (@media, @supports) hit the same prop.key.name crash, but they do nest class names, so skipping them would turn a loud crash into silently wrong output. They need their own handling and are left untouched here.

Testing

A bugs - #30801 keyframes fixture pair plus the idempotency test the other cases use. On master the new case fails with the crash above; with the fix both pass.

Test Files  1 passed (1)
     Tests  41 passed (41)

Whole @mui/codemod package: 686 passed on this branch vs 684 passed on master — the two new tests, no other change. Both runs show the same pre-existing failure, path-imports > should not leak imports between file transformations, which is order-sensitive and unrelated.

eslint and prettier --check --ignore-path .lintignore are clean on the touched files.

`createClasses` read `prop.key.name` for every entry of the JSS style object. JSS
declares keyframes with a string key, `'@Keyframes pulse'`, whose `name` is undefined,
so the codemod threw `undefined does not match field "name"` and no part of the file
was migrated.

A keyframes entry is not a class: neither it nor the percentages it nests may be turned
into a class or into a `& .${classes.x}` selector. Carry it over untouched, and drop the
`$` from the animation names that reference it, since emotion refers to a keyframe by its
bare name.

Closes mui#30801
@code-infra-dashboard

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-49119--material-ui.netlify.app/
QR code for https://deploy-preview-49119--material-ui.netlify.app/

Bundle size

Bundle Parsed size Gzip size
@mui/material 0B(0.00%) 0B(0.00%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/private-theming 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@zannager zannager added the package: codemod Specific to codemod. label Sep 9, 2026
@zannager
zannager requested a review from siriwatknp September 9, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: codemod Specific to codemod.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[codemod] Jss to styled does not support keyframes

2 participants