Update the CSS transition for breadcrumbs
The actual transition length might need adjusting, but this is fairly close to what was requested.
This commit is contained in:
parent
b5f9c4ba8a
commit
1467191a5d
5 changed files with 89 additions and 28 deletions
|
@ -23,6 +23,7 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
|||
import defaultDispatcher from "../../../dispatcher/dispatcher";
|
||||
import Analytics from "../../../Analytics";
|
||||
import { UPDATE_EVENT } from "../../../stores/AsyncStore";
|
||||
import { CSSTransition, TransitionGroup } from "react-transition-group";
|
||||
|
||||
/*******************************************************************
|
||||
* CAUTION *
|
||||
|
@ -36,6 +37,14 @@ interface IProps {
|
|||
}
|
||||
|
||||
interface IState {
|
||||
// Both of these control the animation for the breadcrumbs. For details on the
|
||||
// actual animation, see the CSS.
|
||||
//
|
||||
// doAnimation is to lie to the CSSTransition component (see onBreadcrumbsUpdate
|
||||
// for info). skipFirst is used to try and reduce jerky animation - also see the
|
||||
// breadcrumb update function for info on that.
|
||||
doAnimation: boolean;
|
||||
skipFirst: boolean;
|
||||
}
|
||||
|
||||
export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState> {
|
||||
|
@ -44,6 +53,11 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
|||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
doAnimation: true, // technically we want animation on mount, but it won't be perfect
|
||||
skipFirst: false, // render the thing, as boring as it is
|
||||
};
|
||||
|
||||
BreadcrumbsStore.instance.on(UPDATE_EVENT, this.onBreadcrumbsUpdate);
|
||||
}
|
||||
|
||||
|
@ -54,7 +68,16 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
|||
|
||||
private onBreadcrumbsUpdate = () => {
|
||||
if (!this.isMounted) return;
|
||||
this.forceUpdate(); // we have no state, so this is the best we can do
|
||||
|
||||
// We need to trick the CSSTransition component into updating, which means we need to
|
||||
// tell it to not animate, then to animate a moment later. This causes two updates
|
||||
// which means two renders. The skipFirst change is so that our don't-animate state
|
||||
// doesn't show the breadcrumb we're about to reveal as it causes a visual jump/jerk.
|
||||
// The second update, on the next available tick, causes the "enter" animation to start
|
||||
// again and this time we want to show the newest breadcrumb because it'll be hidden
|
||||
// off screen for the animation.
|
||||
this.setState({doAnimation: false, skipFirst: true});
|
||||
setTimeout(() => this.setState({doAnimation: true, skipFirst: false}), 0);
|
||||
};
|
||||
|
||||
private viewRoom = (room: Room, index: number) => {
|
||||
|
@ -77,14 +100,26 @@ export default class RoomBreadcrumbs2 extends React.PureComponent<IProps, IState
|
|||
)
|
||||
});
|
||||
|
||||
if (tiles.length === 0) {
|
||||
tiles.push(
|
||||
<div className="mx_RoomBreadcrumbs2_placeholder">
|
||||
{_t("No recently visited rooms")}
|
||||
if (tiles.length > 0) {
|
||||
// NOTE: The CSSTransition timeout MUST match the timeout in our CSS!
|
||||
return (
|
||||
<CSSTransition
|
||||
appear={true} in={this.state.doAnimation} timeout={300}
|
||||
classNames='mx_RoomBreadcrumbs2'
|
||||
>
|
||||
<div className='mx_RoomBreadcrumbs2'>
|
||||
{tiles.slice(this.state.skipFirst ? 1 : 0)}
|
||||
</div>
|
||||
</CSSTransition>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div className='mx_RoomBreadcrumbs2'>
|
||||
<div className="mx_RoomBreadcrumbs2_placeholder">
|
||||
{_t("No recently visited rooms")}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <div className='mx_RoomBreadcrumbs2'>{tiles}</div>;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue