I have the following component:
<ReactCSSTransitionGroup
transitionName={transitionName}
transitionAppear={true}
transitionLeave={true}
>
{children}
</ReactCSSTransitionGroup>
And the following css classes:
.slide-appear {
max-height: 0;
}
.slide-appear.slide-appear-active {
max-height: 100vh;
overflow: visible;
transition: max-height 500ms ease-in;
}
.slide-leave {
max-height: 100vh;
}
.slide-leave.menu-leave-active {
overflow: hidden;
max-height: 0px;
transition: max-height 500ms ease;
}
The transitions are working for appear but not for leave.
According to the documentation, you disabled leave animation by using this prop:
transitionLeave={false}
Just remove it, problem solved.
Also as quick reminder, transitionAppear is used to enable animation after initial mount of the component, not to enable enter animation.
Related
inside my react app, users are able to enter data that is saved on the server. The data is saved immediatly, users don't have to press any "save" button. I want to display a short animation (similar to https://codepen.io/Sixclones/pen/VBdeXL) whenever I'm sending data to the server. After doing some research, I figured out that I should use react-transition-group (http://reactcommunity.org/react-transition-group/css-transition).
I made a component savingIcon:
const SavingIcon: React.SFC<SavingIconProps> = ({
className,
saving,
}) => {
return (
<div className={ classNames(className, "saving-icon") }>
<CSSTransition
timeout={ 200 }
classNames="saving"
in={ saving }
>
<div className="saving-balls">
<div className="saving-balls__item" />
<div className="saving-balls__item" />
<div className="saving-balls__item" />
</div>
</CSSTransition>
</div>
);
}
Whenever something is being saved, saving is set to true and I'd like to display the animation.
Inside saving-icon.scss I put the following CSS (I tried out several approaches, therefore there might be some unnecessary css):
#keyframes bouncing {
0% {
transform: translate3d(0, 10px, 0) scale(1.2, 0.85);
}
100% {
transform: translate3d(0, -20px, 0) scale(0.9, 1.1);
}
}
div.saving-icon {
position: sticky;
top: 15vh;
display: flex;
flex-direction: column;
justify-content: end;
height: 84vh;
$anim-drt: 0.4s;
$anim-ease: cubic-bezier(.6, .05, .15, .95);
.saving-enter {
div.saving-balls{
&__item {
background-color: $success-color;
transition: background-color 20ms;
}
}
}
.saving-enter-active {
div.saving-balls{
&__item {
background-color: $active-color;
transition: background-color 20ms;
}
&:nth-child(1) {
animation: bouncing $anim-drt alternate infinite $anim-ease;
transition: animation 1000ms;
}
&:nth-child(2) {
animation: bouncing $anim-drt $anim-drt/4 alternate infinite
$anim-ease backwards;
transition: animation 1000ms;
}
&:nth-child(3) {
animation: bouncing $anim-drt $anim-drt/2 alternate infinite
$anim-ease backwards;
transition: animation 1000ms;
}
}
}
.saving-exit {
div.saving-balls{
&__item {
background-color: $active-color;
transition: background-color 20ms;
}
&:nth-child(1) {
animation: bouncing $anim-drt alternate infinite $anim-ease;
transition: animation 1000ms;
}
&:nth-child(2) {
animation: bouncing $anim-drt $anim-drt/4 alternate infinite
$anim-ease backwards;
transition: animation 1000ms;
}
&:nth-child(3) {
animation: bouncing $anim-drt $anim-drt/2 alternate infinite
$anim-ease backwards;
transition: animation 1000ms;
}
}
}
.saving-exit-active {
div.saving-balls{
&__item {
background-color: $success-color;
transition: background-color 20ms;
transition: animation 1000ms;
}
}
}
div.saving-balls {
width: 3em;
height: 10vh;
z-index: 5;
display: flex;
justify-content: space-between;
align-items: center;
&__item {
width: 0.7em;
height: 0.7em;
border-radius: 50%;
background: $success-color;
}
}
}
My issue is the following:
Usually saving something only takes very short time; not enough time to actually run the animation once. My balls just become red for a split second and return being green (active and success color are some type or red and green). I would like to have the animation running a longer period of time, something around 2 seconds. I tried some hacks using effects, states and timeouts, but they didn't work well and I'd rather use a correct solution instead of some dirty hack.
I'm not very familiar with css transitions and animations, neither with react-transition-group. I hope for some existing easy way to play an animation for a certain minimum amount of time (if the connection is weak, the animation should show until the data is saved).
As an alternative, I accept different suggestions on how to tell the user that his input has been saved instead of an animation at the corner of the page. Currently, everything the user enters is saved, but he might not notice that this happened and search for a "save" button.
For anybody with a similar issue: I solved the issue by using useState and only changing the state value for saving if it indeed changed. I didn't use a transition group.
The working saving component:
const SavingIcon: React.SFC<SavingIconProps> = ({
className,
saving,
}) => {
const [ isSaving, setIsSaving ] = useState(false);
useEffect(() => {
if (isSaving !== saving) setIsSaving(saving);
}, [ saving ]);
return (
<div className={ classNames(className, "saving-icon", {
"saving-active": isSaving
}) }>
<div className="saving-balls">
<div className="saving-balls__item" />
<div className="saving-balls__item" />
<div className="saving-balls__item" />
</div>
</div>
);
}
scss:
#keyframes bouncing {
0% {
transform: translate3d(0, 10px, 0) scale(1.2, 0.85);
}
100% {
transform: translate3d(0, -20px, 0) scale(0.9, 1.1);
}
}
div.saving-icon {
position: fixed;
top: 86px;
right: 1.3vw;
$anim-drt: 0.4s; /* duration */
$anim-ease: cubic-bezier(.6, .05, .15, .95);
&.saving-active {
div.saving-balls {
div.saving-balls__item {
background-color: $active-color;
transition: background-color 20ms;
&:nth-child(1) {
animation: bouncing $anim-drt alternate infinite $anim-ease;
}
&:nth-child(2) {
animation: bouncing $anim-drt $anim-drt/4 alternate infinite
$anim-ease backwards;
}
&:nth-child(3) {
animation: bouncing $anim-drt $anim-drt/2 alternate infinite
$anim-ease backwards;
}
}
}
}
div.saving-balls {
width: 3em;
height: 30px;
z-index: 5;
display: flex;
justify-content: space-between;
align-items: center;
&__item {
width: 0.7em;
height: 0.7em;
border-radius: 50%;
background: $success-color;
}
}
}
Probably a super noobie question, but does anyone know why my onClick is not firing? I have tried changing the z-index in my CSS in case the button was too far back, but this did not change anything.
Here is my button module:
import React from 'react';
import classes from './button.module.css';
const button = (props)=>{
return(
<button onClick={()=>{console.log("hello");props.select()}} className={classes.button}>
<div className={classes.text_center}>
<div className={classes.button_text}>{props.text}</div></div>
</button>
);
}
export default button;
Later on I call the module:
this.state.skills?null:<Button select={()=>{console.log("hi");this.setState({skills:true})}} text={"Skills"}></Button>}.
The button actually displays fine, and the text is passed as a prop, but unfortunately I can't get the onClick to fire. Neither of the two console.log statements fire.
All help is appreciated.
///
As requested in the comments button.module.css:
#font-face {
font-family: 'Raleway';
src: url('../../../Fonts/Raleway/Raleway-Light.ttf') format('truetype') /* IE6-IE8 */
}
.button_choice{
width:10vw;
height:10vh;
top:25%;
border: 2px solid #4ca3dd;
position: relative;
display: inline-block;
margin-left:5vw;
background-color: white;
vertical-align: middle;
border-radius:10px;
padding:5px;
}
.button_choice:hover{
background-color: red;
}
.text_center{
height:100%;
width:100%;
position:relative;
display: table;
}
.text_center:hover{
background-color: blue;
}
.button_text{
font-family:"Raleway";
position:relative;
line-height: 30px;
font-size: 20px;
text-align: center;
display: table-cell;
vertical-align: middle;
}
/////
Slight break through :/, when considering the 3 classes below, .background_init is a div spreading over the whole page. On the press of a button, this div slides to half of the size on the left by changing to the class .background_left. The buttons are contained within background_right. If I change height in .background_left to 200px, the buttons work (including hover), but obviously this completely messes up my styling. Any suggestions?
.background_init{
width:100vw;
height:100vh;
background-color: #4ca3dd;
}
.background_left{
width:50vw;
height:100vh;
background-color: #4ca3dd;
transition: width 2s;
}
.background_right{
overflow: auto;
width:50vw;
height:100vh;
transition: width 2s;
}
I am not sure why this works, but instead of using 100vh and 100vw, I used display:absolute and width:50%/ 100% and height:100%. If anyone can explain why this works I would be extremely grateful.
I am creating a simple Dropdown menu in React. The initial event of the drop down works as expected. However, when retracting the dropdown there is a noticeable delay in the transition despite equal default values.
The CSS transition properties are identical so I am not sure why there is a delay. I have also set the transition delay value of both explicitly to 0, to be sure.
here is the component
class DrawerLink extends React.Component {
constructor() {
super();
this.state = { collapse: false };
this.handleLinkToggle = this.handleLinkToggle.bind(this);
}
handleLinkToggle(e) {
this.setState({ collapse: !this.state.collapse });
}
render() {
const { collapse } = this.state;
return (
<div className="DrawerLinkContainer">
<div onClick={this.handleLinkToggle}>
<div className="image-container">
<img src="../public/images/user.jpeg" />
</div>
<p>Steave Jobs</p>
</div>
<div
className={
collapse ? "sub-menu-container collapse" : "sub-menu-container"
}
>
<p>First Sub Menu</p>
<p>Second Sub Menu</p>
</div>
</div>
);
}
}
and the CSS:
.sub-menu-container {
padding-left: 40px;
max-height: 0px;
overflow: hidden;
transition: max-height 1s linear 0s;
&.collapse {
max-height: 500px;
transition: max-height 1s linear 0s;
}
p {
padding: 7px 35px 7px 15px;
}
}
Because you have set max-height to 500px and your content is only about 60px, the first transition is still executing causing what seems like a delay. I.E increasing to a "max height" of 500px.
You can see better if you set a background colour on the sub container and set the height equal to the max height in the collapse class. Something like:
.sub-menu-container {
padding-left: 40px;
max-height: 500px;
overflow: hidden;
transition: max-height 1s linear 0s;
background: red;
&.collapse {
max-height: 0px;
}
p {
padding: 7px 35px 7px 15px;
}
}
The real solution is to use an animation library because transitions have issues (they just don't work) when element are removed from the DOM by React.
If you need a solution to your example, you need to know the height of the sub container and use that as a max height. It's not very dynamic though.
I'm trying to get a height animation working using Angular JS 1.2. I've got a plunker here that has the animation working for closing the item:
http://plnkr.co/edit/YVtnXgjO3Evb6tz5DJOp?p=preview
With the key bit being this CSS here:
.accordion-body {
height: 100px;
-webkit-transition: 0.5s linear all;
transition: 0.5s linear all;
}
.accordion-body.ng-hide-add,
.animate-show.ng-hide-remove {
display: block !important;
}
.accordion-body.ng-hide-add{
}
.accordion-body.ng-hide-remove{
}
.accordion-body.ng-hide {
height:0;
}
But I can't figure out how to get it to work for opening the item. I'm obviously doing something braindead - what am I missing?
Got it working with the following CSS:
.accordion-body {
height: 100px;
-webkit-transition: 0.5s linear all;
transition: 0.5s linear all;
}
.accordion-body.ng-hide-add,
.accordion-body.ng-hide-remove {
display: block !important;
height: 0px;
}
.accordion-body.ng-hide-remove.ng-hide-remove-active {
height: 100px;
}
.accordion-body.ng-hide-add{
height: 100px;
}
.accordion-body.ng-hide-add.ng-hide-add-active {
height: 0;
}
You messed up a class name is all.
I'm using ngAnimate to animate max-height for a simple slide-toggle effect, and there's something a bit strange happening: when hiding, it seems that setting the transition property on the setup class (.xxx-hide) doesn't work--the height snaps to 0 immediately:
.controls-hide {
-webkit-transition-duration: 1s;
-moz-transition-duration: 1s;
-o-transition-duration: 1s;
transition-duration: 1s;
max-height: 5em;
opacity: 1;
}
.controls-hide.controls-hide-active {
max-height: 0em;
opacity: 0;
}
But setting it on the active class (.xxx-hide.xxx-hide-active), the animation works just fine:
.othercontrols-hide {
opacity: 1;
max-height: 5em;
}
.othercontrols-hide.othercontrols-hide-active {
-webkit-transition-duration: 1s;
-moz-transition-duration: 1s;
-o-transition-duration: 1s;
transition-duration: 1s;
max-height: 0em;
opacity: 0;
}
(Here's the whole fiddle.)
Even more strangely, the opacity animates just fine in both cases. What's going on here?
I just follow the instructions at this site: http://www.nganimate.org/angularjs/ng-repeat/appear
And I got this fiddle working: http://jsfiddle.net/WXWSu/2/
What I changed was set the transtion tag to all changes (transition: 1s linear all;), and set the start properties at the main class:
.exercise-controls {
overflow: hidden;
border: 1px solid black;
height: 5em;
opacity: 1;
}