3

I am trying to animate a button when hovered using styled from MUI 5 - but it is not working. I tried to find inspiration from:

.. with no luck.

Try and have a look and tell what I cannot see:

import Button from "@mui/material/Button";
import { styled } from "@mui/material/styles";
import { keyframes } from "@emotion/react";

const getAnimation = () => keyframes`
    0 %  { transform: translate(1px, 1px)   rotate(0deg)    },
    10%  { transform: translate(-1px, -2px) rotate(-1deg);  },
    20%  { transform: translate(-3px, 0px)  rotate(1deg);   },
    30%  { transform: translate(3px, 2px)   rotate(0deg);   },
    40%  { transform: translate(1px, -1px)  rotate(1deg);   },
    50%  { transform: translate(-1px, 2px)  rotate(-1deg);  },
    60%  { transform: translate(-3px, 1px)  rotate(0deg);   },
    70%  { transform: translate(3px, 1px)   rotate(-1deg);  },
    80%  { transform: translate(-1px, -1px) rotate(1deg);   },
    90%  { transform: translate(1px, 2px)   rotate(0deg);   },
    100% { transform: translate(1px, -2px)  rotate(-1deg);  }
`;

const StyledButton = styled((props) => {
  const { ...other } = props;
  return <Button {...other} />;
})(({ theme }) => ({
  ":hover": {
    animation: `${getAnimation} shake infinite`
  },
  backgroundColor: "#2699FB",
  color: "#FFFFFF"
}));

const App = () => {
  return (
    <StyledButton variant="contained">
              My button
    </StyledButton>
  )
}

export default App
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
Delice
  • 743
  • 9
  • 20

2 Answers2

3

Emotion's keyframe is a tag function. It accepts a template string as the first argument and returns the keyframe data. What you defined in your code is a function that just returns another function without doing anything:

const getAnimation = () => keyframes`
    0 %  { transform: translate(1px, 1px)   rotate(0deg)    },
    ...
    100% { transform: translate(1px, -2px)  rotate(-1deg);  }
`;

You're supposed to change the code to this:

const myKeyframe = keyframes`
    0 %  { transform: translate(1px, 1px)   rotate(0deg)    },
    ...
    100% { transform: translate(1px, -2px)  rotate(-1deg);  }
`;

Usage

const StyledButton = styled((props) => <Button {...props} />)(({ theme }) => ({
  ":hover": {
    backgroundColor: "#2699FB",
    // I also fixed the animation sub-property order of yours
    // See: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations#configuring_the_animation
    animation: `${myKeyframe} 1s infinite ease`
  },
  backgroundColor: "#2699FB",
  color: "#FFFFFF"
}));

Live Demo

Codesandbox Demo

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
2

This s eem to work for me

  1. Inside sx prop
<Box
  sx={{
    animationName: "move",  
    "@keyframes move": {
       "0%": {
         opacity: 0,
       },
       "50%": {
         opacity: 1,
       },
       "100%": {
         opacity: 0,
        },
    },          
  }}
>
 Content
</Box>

or

2)

import { keyframes } from "@mui/system";

...

const shake = keyframes`
  25% { transform: translateX(-1px); }    
  75% { transform: translateX(1px); }
`;

...

<Box
  sx={{
    animation: `${shake} .5s linear infinite;`,
    width: "75px",
    height: "75px",
  }}
>
...
</Box>
atazmin
  • 4,757
  • 1
  • 32
  • 23