Reputation: 6505
I'm trying to create reusable animations in Emotion but have run into some issues. I've defined an animation for a fadeUp
effect which works fine.
export const animatedFadeUp = css`
opacity: 1;
transform: translateY(0);
`;
export const fadeUp = css`
opacity: 0;
transform: translateY(var(--spacing-medium));
transition: opacity 0.5s ease-in-out,
transform 0.5s ease-in-out;
html.no-js & {
${animatedFadeUp}
}
`;
But when i try to apply the fadeUp
animation to an element that already has the transition defined it gets overruled. For example the button below. The transition
will be overruled by the button
.
const Button = styled.button`
${fadeUp}
background: orange;
transition: background-color 0.5s ease-in-out;
&:hover,
&:focus {
background: gold;
}
`;
Is there a solution to combine only a single property? Something like:
const Button = styled.button`
${fadeUp}
background: orange;
transition: ${fadeUp.transition},
background-color 0.5s ease-in-out;
&:hover,
&:focus {
background: gold;
}
`;
Upvotes: 6
Views: 3814
Reputation: 3604
Instead of passing it as a CSS tagged template literals or using styled components, you may use it as CSS object. By using as such, it would be more flexible and easier to refer their properties.
<p
css={{
color: 'red'
}}
>Hello World</p>
So your code would become
export const animatedFadeUp = {
opacity: 1,
transform: 'translateY(0)',
};
export const fadeUp = {
opacity: 0,
transform: 'translateY(var(--spacing-medium))',
transition: `opacity 0.5s ease-in-out,
transform 0.5s ease-in-out`,
['html.no-js &']: {
...animatedFadeUp
}
};
const App = () => (
<button
css={{
...fadeUp,
background: 'orange',
transition: `${fadeUp.transition},
background-color 0.5s ease-in-out`,
['&:hover']: {
background: 'gold',
},
['&:focus']: {
background: 'gold',
}
}}
>Click Me</button>
)
Upvotes: 4
Reputation: 1180
Not quite familiar with the Emotion
library, maybe there is an API that exposes style value access like you tried with ${fadeUp.transition}
. But I won't be surprised if there is no such API as it increases the complexity of the library. However, hope is not lost, without knowing much of the API, we can still solve this problem using language features supported by javascript. Below is an example:
import React, { useState } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/react';
export const animatedFadeUp = css`
opacity: 1;
transform: translateY(0);
`;
// Notice that the annoymous function is invoked immediately to get back an object
// with properties of `css` and `transition`, so that we can access them later
export const fadeUp = (() => {
// By defining the transition value here, we can update the transition value in one
// place instead of updating in multiple places, including the downstream consumers
// of the returned object
const transition = 'opacity 0.5s ease-in-out, transform 0.5s ease-in-out';
return {
css: css`
opacity: 0;
transform: translateY(25px);
transition: ${transition};
&.active {
${animatedFadeUp}
}
`,
transition,
};
})();
// Note that we need to access the `css` property explicitly here
// like this - ${fadeUp.css}
const Button = styled.button`
${fadeUp.css}
background: green;
transition: ${fadeUp.transition}, background-color 0.5s ease-in-out;
&:hover,
&:focus,
&.active {
background: gold;
}
`;
function App() {
const [className, setClassName] = useState('');
return (
<div className="App">
<Button className={className}>This my button component.</Button>
<button onClick={() => setClassName(className ? '' : 'active')}>
Toggle
</button>
</div>
);
}
export default App;
In short, we create an object that holds the information of the css
and transition
so that we can use it later. The downside of this approach is that we need to remember that when using fadeUp
, we have to treat it differently by explicitly accessing fadeUp.css
, unlike other emotion
created css.
Upvotes: 0