From decc1ae9079c6320fe355488021559f2b19ce9e0 Mon Sep 17 00:00:00 2001 From: Siim Halapuu Date: Fri, 21 Oct 2016 09:16:36 +0300 Subject: [PATCH] Add `changeWidth` param to allow animating width Previously it was only possible to animate the height of the component. This adds the possibility to animate width together with height. Width change animation can be enabled by passing in `changeWidth: true` in props for the component. This change is backwards compatible. --- README.md | 4 ++++ src/ReactCSSTransitionReplace.jsx | 35 +++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f3ae693..15da06f 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,10 @@ and the new component animated in. During this process: This provides many possibilities for animating the replacement as illustrated in the examples below. +Additionally, `changeWidth` can be used to animate changing the width of the component. This change +will happen at the same time as changing the height. Animating this change should be done using +the same class name as is used for animating the change of height. + It is also possible to remove the child component (i.e. leave `ReactCSSTransitionReplace` with no children) which will animate the `height` going to zero along with the `leave` transition. Similarly, a single child can be added to an empty `ReactCSSTransitionReplace`, triggering the inverse animation. diff --git a/src/ReactCSSTransitionReplace.jsx b/src/ReactCSSTransitionReplace.jsx index 734f712..9c728ba 100644 --- a/src/ReactCSSTransitionReplace.jsx +++ b/src/ReactCSSTransitionReplace.jsx @@ -63,7 +63,8 @@ export default class ReactCSSTransitionReplace extends React.Component { transitionAppearTimeout: createTransitionTimeoutPropValidator('Appear'), transitionEnterTimeout: createTransitionTimeoutPropValidator('Enter'), transitionLeaveTimeout: createTransitionTimeoutPropValidator('Leave'), - overflowHidden: React.PropTypes.bool + overflowHidden: React.PropTypes.bool, + changeWidth: React.PropTypes.bool }; static defaultProps = { @@ -71,7 +72,8 @@ export default class ReactCSSTransitionReplace extends React.Component { transitionEnter: true, transitionLeave: true, overflowHidden: true, - component: 'span' + component: 'span', + changeWidth: false }; state = { @@ -80,6 +82,7 @@ export default class ReactCSSTransitionReplace extends React.Component { nextChild: undefined, nextChildKey: '', height: null, + width: null, isLeaving: false }; @@ -118,7 +121,8 @@ export default class ReactCSSTransitionReplace extends React.Component { this.setState({ nextChild, nextChildKey: state.currentChildKey ? String(Number(state.currentChildKey) + 1) : '1', - height: state.currentChild ? ReactDOM.findDOMNode(this.refs.curr).offsetHeight : 0 + height: state.currentChild ? ReactDOM.findDOMNode(this.refs.curr).offsetHeight : 0, + width: state.currentChild && this.props.changeWidth ? ReactDOM.findDOMNode(this.refs.curr).offsetWidth : null }); // Enqueue setting the next height to trigger the height transition. @@ -141,12 +145,18 @@ export default class ReactCSSTransitionReplace extends React.Component { enqueueHeightTransition(nextChild, tickCount = 0) { this.timeout = setTimeout(() => { if (!nextChild) { - return this.setState({height: 0}); + return this.setState({ + height: 0, + width: this.props.changeWidth ? 0 : null + }); } const nextNode = ReactDOM.findDOMNode(this.refs.next); if (nextNode) { - this.setState({height: nextNode.offsetHeight}); + this.setState({ + height: nextNode.offsetHeight, + width: this.props.changeWidth ? nextNode.offsetWidth : null + }); } else { // The DOM hasn't rendered the entering element yet, so wait another tick. @@ -181,7 +191,8 @@ export default class ReactCSSTransitionReplace extends React.Component { currentChildKey: state.nextChildKey, nextChild: undefined, nextChildKey: '', - height: null + height: null, + width: null }); } @@ -200,6 +211,7 @@ export default class ReactCSSTransitionReplace extends React.Component { if (!this.state.nextChild) { this.isTransitioning = false; state.height = null; + state.width = null; } this.setState(state); @@ -212,7 +224,8 @@ export default class ReactCSSTransitionReplace extends React.Component { return this.setState({ nextChild: undefined, nextChildKey: '', - height: null + height: null, + width: null }); } @@ -240,11 +253,11 @@ export default class ReactCSSTransitionReplace extends React.Component { } render() { - const { currentChild, currentChildKey, nextChild, nextChildKey, height, isLeaving } = this.state; + const { currentChild, currentChildKey, nextChild, nextChildKey, height, width, isLeaving } = this.state; const childrenToRender = []; const { overflowHidden, transitionName, component, - transitionAppear, transitionEnter, transitionLeave, + transitionAppear, transitionEnter, transitionLeave, changeWidth, transitionAppearTimeout, transitionEnterTimeout, transitionLeaveTimeout, ...containerProps } = this.props; @@ -277,6 +290,10 @@ export default class ReactCSSTransitionReplace extends React.Component { if (overflowHidden) { containerProps.style.overflow = 'hidden'; } + + if (changeWidth) { + containerProps.style.width = width; + } } if (nextChild) {