Styled-components, SVG not animating - css

I use styled-components alongside React and I have such component:
import styled, { keyframes } from 'styled-components'
import { ReactComponent as SpinnerIcon } from './spinner.svg'
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`
const Spinner = styled(SpinnerIcon)`
margin-top: 50px;
animation: ${rotate} 2s ease-in infinite;
`
export default Spinner
When I use this component like this:
<Spinner width='50px' height='50px' />
I see this component but it's not animating. What's wrong?

Try this:
const Spinner = styled.img.attrs({
src: SpinnerIcon,
})`
margin-top: 50px;
animation: ${rotate} 2s ease-in infinite;
if this doesn't work for you please share your svg file too. Also you probably need use linear function instead of ease-in
`

Related

How can I animate from an alternating keyframe animation to a fixed value

Is it possible for an element that is being animated using keyframes to animate to a fixed value for that property? My use case is a draggable element whose scale is pulsing until clicked, but when clicked it should have a fixed size. I would like the element to animate to that new size.
This example uses styled-components.
const pulse = keyframes`
from {
transform: scale(1);
}
to {
transform: scale(1.05);
}
`
const AnimatedThing = styled(div)`
${({ isDragging }) =>
isDragging ?
'transform: scale(1.2);' :
`animation: ${pulse} 0.5s alternate infinite;`
}
`
As you can see in the code, when isDragging is true, scale is set to 1.2. Right now it just jumps to that value, but I want it to animate to that value.
I tried using css variables and animating those, and couldn't get that to work either. That code is a bit more complex but you can see it here
const pulse = keyframes`
from {
transform: scale(var(--pulse-start-scale));
}
to {
transform: scale(var(--pulse-end-scale))
}
`
const AnimatedGroup = styled(div)`
#property --pulse-start-scale {
syntax: '<number>';
inherits: false;
initial-value: 1;
}
#property --pulse-end-scale {
syntax: '<number>';
inherits: false;
initial-value: 1.05;
}
transition: --pulse-start-scale --pulse-end-scale 1s;
animation: ${pulse} 0.5s alternate infinite;
${({ $active }) =>
$active &&
`
--pulse-end-scale: 1.2;
--pulse-start-scale: 1.2;
`}
`

There's some way to add fadein or slide effect on "react-dates-range" when i change between months?

I'm using the library https://github.com/hypeserver/react-date-range , react 17.0.2 and next 12.0.0
I would like that when I change from one month to another, instead of making a sudden change, to be able to configure a Fade-In, or a Slide, just as it happens in the AirBnb calendar.
Does anyone know how I can do this? Thank you very much and sorry for the inconvenience.
This is my actual behavior
This is something like what I want, but it could also be a fade in or something similar.
Exactly like Airbnb i believe its not possible because the react-date-range works a little different from what airbnb does.
But you can get similar behavior using SwitchTransition and CSSTransition from react-transition-group library. You can check their docs here.
First, here's the code sample with DateRangerPicker using CSSTransition between months.
And below the same code, with comments on what its doing:
CSS file:
/*
Overflow the Calendar container
.rdrDateRangeWrapper is a class that react-date-range creates internally
*/
.rdrDateRangeWrapper {
overflow-x: hidden;
}
/*
.rdrMonths is the class that react-date-range creates internally for the month container calendar
.fadeRightToLeft classes is related to react-transition-group
Created for transition from right to left
*/
.fadeRightToLeft-enter .rdrMonths {
opacity: 0;
transform: translateX(100%);
}
.fadeRightToLeft-enter-active .rdrMonths {
opacity: 1;
transform: translateX(0%);
}
.fadeRightToLeft-exit .rdrMonths {
opacity: 1;
transform: translateX(0%);
}
.fadeRightToLeft-exit-active .rdrMonths {
opacity: 0;
transform: translateX(-100%);
}
.fadeRightToLeft-enter-active .rdrMonths,
.fadeRightToLeft-exit-active .rdrMonths {
transition: opacity 100ms, transform 100ms;
}
/*
Same as fadeRightToLeft:
.fadeLeftToRight classes is related to react-transition-group
Created for transition from left to right
*/
.fadeLeftToRight-enter .rdrMonths {
opacity: 0;
transform: translateX(-100%);
}
.fadeLeftToRight-enter-active .rdrMonths {
opacity: 1;
transform: translateX(0%);
}
.fadeLeftToRight-exit .rdrMonths {
opacity: 1;
transform: translateX(0%);
}
.fadeLeftToRight-exit-active .rdrMonths {
opacity: 0;
transform: translateX(100%);
}
.fadeLeftToRight-enter-active .rdrMonths,
.fadeLeftToRight-exit-active .rdrMonths {
transition: opacity 100ms, transform 100ms;
}
Component file:
import { useState } from "react";
import { addDays, isAfter } from "date-fns";
import { DateRangePicker } from "react-date-range";
import { SwitchTransition, CSSTransition } from "react-transition-group";
import "react-date-range/dist/styles.css";
import "react-date-range/dist/theme/default.css";
import "./styles.css";
export default function App() {
const [state, setState] = useState([
{
startDate: new Date(),
endDate: addDays(new Date(), 7),
key: "selection"
}
]);
// state created to hold the first month that calendar is showing
const [shownDateChangeValue, setShownDateChangeValue] = useState(new Date());
// state created to check if use created next Month ou previous month
const [isNextMonth, setIsNextMonth] = useState(true);
return (
<SwitchTransition mode="out-in">
<CSSTransition
/*** call the transition when month changes ***/
key={shownDateChangeValue}
/*** code related to SwitchTransition ***/
addEndListener={(node, done) =>
node.addEventListener("transitionend", done, false)
}
/*** Set the transition class related to the user action ***/
classNames={isNextMonth ? "fadeRightToLeft" : "fadeLeftToRight"}
>
<DateRangePicker
onChange={(item) => {
setState([item.selection]);
}}
showSelectionPreview={true}
moveRangeOnFirstSelection={false}
months={2}
ranges={state}
direction="horizontal"
/*** set the current month ***/
shownDate={shownDateChangeValue}
/*** Change shownDateChangeValue and isNextMonth states, dispatching the transition ***/
onShownDateChange={(month) => {
/* check if user click next or previous month */
const isNext = isAfter(month, shownDateChangeValue);
setIsNextMonth(isNext ? true : false);
setShownDateChangeValue(month);
}}
/>
</CSSTransition>
</SwitchTransition>
);
}

CSS rotation problem found when execute it in edge

I wrote some pieces of codes in angular about rotating an icon by pressing a toggle button in angular.
When I run it in chrome everything is OK but in Edge rotation process works properly but final rotation status is 180 degree reverse.
Here is my snippets:
my .ts file:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-menutest',
templateUrl: './menutest.component.html',
styleUrls: ['./menutest.component.scss']
})
export class MenutestComponent implements OnInit {
public classChangesRotation: {[key: string]: string} = {};
public expandeds: {[key: string]: boolean} = {};
private zero: string;
constructor() {
this.zero = 'zero';
this.expandeds[this.zero] = true;
this.classChangesRotation[this.zero] = 'rotate-expanded';
}
expansion_click(divName: string) {
this.expandeds[divName] = !this.expandeds[divName];
if (this.expandeds[divName]) {
this.classChangesRotation[divName] = 'rotate-expanded';
} else {
this.classChangesRotation[divName] = 'rotate-collapsed';
}
}
}
my html file:
<button mat-raised-button (click)="expansion_click('zero')">
Expand and Collapse
<mat-icon [ngClass]="classChangesRotation['zero']">
chevron_left
</mat-icon>
</button>
and my scss file contains :
.rotate-expanded {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
transition: -webkit-transform 150ms;
transition: transform 150ms;
transition: transform 150ms,-webkit-transform 150ms;
transition-timing-function: ease-in-out;
}
.rotate-collapsed {
-webkit-transform: rotate(0);
transform: rotate(0);
transition: -webkit-transform 150ms;
transition: transform 150ms;
transition: transform 150ms,-webkit-transform 150ms;
transition-timing-function: ease-in-out;
}
As I mentioned above when I run these codes in chrome everything is OK and normal but in Edge the animation process is fine but final rotation differs 180 degrees!
Do you have any idea?
Thank you for your attentions.
Pay attention please:
You should know that direction of this code is right to left and result in LTR direction is OK but the problem is in RTL direction. I understand it right now and added it to my question.

How to make slideIn AND slideOut with styled-components with react-animations

I'm working on building a component that displays none or block depending on it's isActive prop.
I've managed to make it slideInDown using react-animations with styled-components like this.
import styled, { keyframes } from 'styled-components';
import { ifProp } from 'styled-tools';
import { slideInDown } from 'react-animations';
const slideInAnimation = keyframes`${slideInDown}`;
const MyComponent = styled.div`
animation: 0.4s ${slideInAnimation};
display: ${ifProp('isActive', 'block', 'none')};
`;
I need to make it slideOutUp now. However, I'm not sure how to implement both slideInDown and slideOutUp animations together.
How would I accomplish that?
Note: that works. But I don't know how to make it both slide in and out. I tried something like this below but that didn't work.
import styled, { keyframes } from 'styled-components';
import { ifProp } from 'styled-tools';
import { slideInDown, slideOutUp } from 'react-animations';
const slideInAnimation = keyframes`${slideInDown}`;
const slideOutAnimation = keyframes`${slideOutUp}`;
const MyComponent = styled.div`
animation: 0.4s ${slideInAnimation}, 0.4s ${slideOutAnimation};
display: ${ifProp('isActive', 'block', 'none')};
`;
I went through the react-animations library, what I figured out is slideOutUp sets visibility: 'hidden.'
const slideOutUp: Animation = {
from: {
transform: translate3d(0, 0, 0)
},
to: {
visibility: 'hidden',
transform: translate3d(0, '-100%', 0)
}
};
You can use animation-fill-mode: forwards, which helps in retaining the style after the animation ends.
You can do something like this (it works):
const MyComponent = styled.div`
animation: ${ifProp(
"isActive",
`0.4s ${slideInAnimation}`,
`0.4s ${slideOutAnimation} forwards`
)};
`;
Here is the working example, for testing purpose onClick event I am setting {isActive: false}
https://codesandbox.io/s/949ql6p6no
Display does not animate. You need to use opacity for toggling (1 to 0 and vice versa) and animation.
const myComponent = styled.div`
animation: 0.4s ${slideInAnimation};
opacity: ${ifProp('isActive', 1, 0)};
`;
Considering that your code is working like you told me, you can use the attribute infinte at animation:
animation: 0.4s ${slideInAnimation} infinite;
I guess that it solves your problem.

CSSTransitionGroup doesn't fade in

I am quite new to react and I am trying to build a react app. I want a login box to fade in on the page when the login in the navbar is clicked. In my App.js I set up the CSSTransitionGroup like this:
<CSSTransitionGroup
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
transitionAppear={true}
transitionAppearTimeout={500}
transitionName="fade">
{loginPopup}
</CSSTransitionGroup>
The login popup is shown based on state:
let loginPopup;
if (display_login) {
loginPopup = (<LoginPopup key={1} />)
}
Now the css I use for the transition looks like this:
//fade
.fade-appear {
opacity: 0.01;
}
.fade-appear-active {
opacity: 1;
transition: opacity 300ms ease-in;
}
.fade-leave {
opacity: 1;
}
.fade-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;
}
My problem is...that the fadeout works as intended, but the fadein does not work. It just pops up (no transition).
I also tried using .fade-enter - But I figured that enter was wrong as the LoginPopup component is spawned based on state.
Any ideas why the fade in don't work?
Edit:
This is the gist of the code: https://gist.github.com/xenoxsis/6345eb6897aedf228662ffaf64f65053

Resources