1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Use setTimeout instead of unstable onTransitionEnd

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Alex Andreev 2021-11-24 13:09:24 +03:00
parent 5d172b89db
commit 4a3c31369c
3 changed files with 30 additions and 30 deletions

View File

@ -21,43 +21,43 @@
// Animations // Animations
@mixin animate-opacity($enterDuration: 100ms, $leaveDuration: 150ms) { @mixin animate-opacity() {
opacity: 0; opacity: 0;
&.enter { &.enter {
transition-property: opacity; transition-property: opacity;
transition-duration: $enterDuration; transition-duration: var(--enter-duration);
opacity: 1; opacity: 1;
} }
&.leave { &.leave {
transition-duration: $leaveDuration; transition-duration: var(--leave-duration);
transition-timing-function: ease-out; transition-timing-function: ease-out;
opacity: 0; opacity: 0;
} }
} }
@mixin animate-slide-right($enterDuration: 100ms, $leaveDuration: 150ms) { @mixin animate-slide-right() {
transform: translateX(100%); transform: translateX(100%);
will-change: transform; will-change: transform;
&.enter { &.enter {
transform: translateX(0); transform: translateX(0);
transition: transform $enterDuration; transition: transform var(--enter-duration);
transition-timing-function: ease-in-out; transition-timing-function: ease-in-out;
} }
&.leave { &.leave {
transform: translateX(100%); transform: translateX(100%);
transition: transform $leaveDuration; transition: transform var(--leave-duration);
} }
} }
@mixin animate-opacity-scale($enterDuration: 250ms, $leaveDuration: 150ms) { @mixin animate-opacity-scale() {
opacity: 0; opacity: 0;
&.enter { &.enter {
transition: opacity $enterDuration; transition: opacity var(--enter-duration);
opacity: 1; opacity: 1;
} }
@ -65,7 +65,7 @@
will-change: opacity, transform; will-change: opacity, transform;
opacity: 0; opacity: 0;
transform: scale(1.25); transform: scale(1.25);
transition: transform $leaveDuration ease-in, opacity $leaveDuration ease-out; transition: transform var(--leave-duration) ease-in, opacity var(--leave-duration) ease-out;
} }
} }
@ -84,6 +84,6 @@
} }
&.opacity-scale { &.opacity-scale {
@include animate-opacity-scale(100ms); @include animate-opacity-scale;
} }
} }

View File

@ -23,7 +23,7 @@ import "./animate.scss";
import React from "react"; import React from "react";
import { observable, reaction, makeObservable } from "mobx"; import { observable, reaction, makeObservable } from "mobx";
import { disposeOnUnmount, observer } from "mobx-react"; import { disposeOnUnmount, observer } from "mobx-react";
import { boundMethod, cssNames, noop } from "../../utils"; import { cssNames, noop } from "../../utils";
export type AnimateName = "opacity" | "slide-right" | "opacity-scale" | string; export type AnimateName = "opacity" | "slide-right" | "opacity-scale" | string;
@ -32,17 +32,19 @@ export interface AnimateProps {
enter?: boolean; enter?: boolean;
onEnter?: () => void; onEnter?: () => void;
onLeave?: () => void; onLeave?: () => void;
enterDuration?: number;
leaveDuration?: number;
} }
@observer @observer
export class Animate extends React.Component<AnimateProps> { export class Animate extends React.Component<AnimateProps> {
static VISIBILITY_DELAY_MS = 0;
static defaultProps: AnimateProps = { static defaultProps: AnimateProps = {
name: "opacity", name: "opacity",
enter: true, enter: true,
onEnter: noop, onEnter: noop,
onLeave: noop, onLeave: noop,
enterDuration: 100,
leaveDuration: 100,
}; };
@observable isVisible = !!this.props.enter; @observable isVisible = !!this.props.enter;
@ -66,7 +68,6 @@ export class Animate extends React.Component<AnimateProps> {
if (enter) this.enter(); if (enter) this.enter();
else this.leave(); else this.leave();
}, { }, {
delay: Animate.VISIBILITY_DELAY_MS,
fireImmediately: true, fireImmediately: true,
}), }),
]); ]);
@ -84,6 +85,11 @@ export class Animate extends React.Component<AnimateProps> {
if (!this.isVisible) return; if (!this.isVisible) return;
this.statusClassName.leave = true; this.statusClassName.leave = true;
this.props.onLeave(); this.props.onLeave();
this.resetAfterLeaveDuration();
}
resetAfterLeaveDuration() {
setTimeout(() => this.reset(), this.props.leaveDuration);
} }
reset() { reset() {
@ -92,27 +98,21 @@ export class Animate extends React.Component<AnimateProps> {
this.statusClassName.leave = false; this.statusClassName.leave = false;
} }
@boundMethod
onTransitionEnd(evt: React.TransitionEvent) {
const { enter, leave } = this.statusClassName;
const { onTransitionEnd } = this.contentElem.props;
if (onTransitionEnd) onTransitionEnd(evt);
// todo: check evt.propertyName and make sure all animating props has finished their transition
if (enter && leave) {
this.reset();
}
}
render() { render() {
const { name } = this.props; const { name, enterDuration, leaveDuration } = this.props;
const contentElem = this.contentElem; const contentElem = this.contentElem;
const durations = {
"--enter-duration": `${enterDuration}ms`,
"--leave-duration": `${leaveDuration}ms`,
} as React.CSSProperties;
return React.cloneElement(contentElem, { return React.cloneElement(contentElem, {
className: cssNames("Animate", name, contentElem.props.className, this.statusClassName), className: cssNames("Animate", name, contentElem.props.className, this.statusClassName),
children: this.isVisible ? contentElem.props.children : null, children: this.isVisible ? contentElem.props.children : null,
onTransitionEnd: this.onTransitionEnd, style: {
...contentElem.props.style,
...durations,
},
}); });
} }
} }

View File

@ -167,7 +167,7 @@ export class Dialog extends React.PureComponent<DialogProps, DialogState> {
if (animated) { if (animated) {
dialog = ( dialog = (
<Animate enter={this.isOpen} name="opacity-scale"> <Animate enter={this.isOpen} name="opacity-scale" enterDuration={200} leaveDuration={200}>
{dialog} {dialog}
</Animate> </Animate>
); );