Skip to content

Commit

Permalink
Merge pull request react-bootstrap#1024 from taion/fix-transitions
Browse files Browse the repository at this point in the history
[fixed] Only calculate overlay position on display
  • Loading branch information
taion committed Jul 21, 2015
2 parents 25aacd6 + 7836ba0 commit 1160c50
Show file tree
Hide file tree
Showing 7 changed files with 523 additions and 396 deletions.
76 changes: 39 additions & 37 deletions src/Collapse.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,86 +113,88 @@ class Collapse extends React.Component {
}
}

// Explicitly copied from Transition for doc generation.
// TODO: Remove duplication once #977 is resolved.

Collapse.propTypes = {
/**
* Collapse the Component in or out.
* Show the component; triggers the expand or collapse animation
*/
in: React.PropTypes.bool,
in: React.PropTypes.bool,

/**
* Provide the duration of the animation in milliseconds, used to ensure that finishing callbacks are fired even if the
* original browser transition end events are canceled.
* Unmount the component (remove it from the DOM) when it is collapsed
*/
duration: React.PropTypes.number,
unmountOnExit: React.PropTypes.bool,

/**
* Specifies the dimension used when collapsing.
*
* _Note: Bootstrap only partially supports 'width'!
* You will need to supply your own css animation for the `.width` css class._
* Run the expand animation when the component mounts, if it is initially
* shown
*/
dimension: React.PropTypes.oneOfType([
React.PropTypes.oneOf(['height', 'width']),
React.PropTypes.func
]),
transitionAppear: React.PropTypes.bool,

/**
* A function that returns the height or width of the animating DOM node. Allows for providing some custom logic how much
* Collapse component should animate in its specified dimension.
*
* `getDimensionValue` is called with the current dimension prop value and the DOM node.
* Duration of the collapse animation in milliseconds, to ensure that
* finishing callbacks are fired even if the original browser transition end
* events are canceled
*/
getDimensionValue: React.PropTypes.func,
duration: React.PropTypes.number,

/**
* A Callback fired before the component starts to expand.
* Callback fired before the component expands
*/
onEnter: React.PropTypes.func,

/**
* A Callback fired immediately after the component starts to expand.
* Callback fired after the component starts to expand
*/
onEntering: React.PropTypes.func,

/**
* A Callback fired after the component has expanded.
* Callback fired after the component has expanded
*/
onEntered: React.PropTypes.func,

/**
* A Callback fired before the component starts to collapse.
* Callback fired before the component collapses
*/
onExit: React.PropTypes.func,

/**
* A Callback fired immediately after the component starts to collapse.
* Callback fired after the component starts to collapse
*/
onExiting: React.PropTypes.func,

/**
* A Callback fired after the component has collapsed.
* Callback fired after the component has collapsed
*/
onExited: React.PropTypes.func,

/**
* Specify whether the transitioning component should be unmounted (removed from the DOM) once the exit animation finishes.
* The dimension used when collapsing, or a function that returns the
* dimension
*
* _Note: Bootstrap only partially supports 'width'!
* You will need to supply your own CSS animation for the `.width` CSS class._
*/
unmountOnExit: React.PropTypes.bool,
dimension: React.PropTypes.oneOfType([
React.PropTypes.oneOf(['height', 'width']),
React.PropTypes.func
]),

/**
* Specify whether the component should collapse or expand when it mounts.
* Function that returns the height or width of the animating DOM node
*
* Allows for providing some custom logic for how much the Collapse component
* should animate in its specified dimension. Called with the current
* dimension prop value and the DOM node.
*/
transitionAppear: React.PropTypes.bool
getDimensionValue: React.PropTypes.func
};

Collapse.defaultProps = {
in: false,
in: false,
duration: 300,
dimension: 'height',
transitionAppear: false,
unmountOnExit: false,
transitionAppear: false,

dimension: 'height',
getDimensionValue
};

export default Collapse;

69 changes: 30 additions & 39 deletions src/Fade.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,78 @@ import React from 'react';
import Transition from './Transition';

class Fade extends React.Component {

constructor(props, context){
super(props, context);
}

render() {
return (
<Transition
{...this.props}
in={this.props.in}
className='fade'
enteredClassName='in'
enteringClassName='in'
>
{ this.props.children }
{this.props.children}
</Transition>
);
}
}

// Explicitly copied from Transition for doc generation.
// TODO: Remove duplication once #977 is resolved.

Fade.propTypes = {
/**
* Fade the Component in or out.
* Show the component; triggers the fade in or fade out animation
*/
in: React.PropTypes.bool,
in: React.PropTypes.bool,

/**
* Provide the duration of the animation in milliseconds, used to ensure that finishing callbacks are fired even if the
* original browser transition end events are canceled.
* Unmount the component (remove it from the DOM) when it is faded out
*/
duration: React.PropTypes.number,
unmountOnExit: React.PropTypes.bool,

/**
* A Callback fired before the component starts to fade in.
* Run the fade in animation when the component mounts, if it is initially
* shown
*/
onEnter: React.PropTypes.func,
transitionAppear: React.PropTypes.bool,

/**
* A Callback fired immediately after the component has started to faded in.
* Duration of the fade animation in milliseconds, to ensure that finishing
* callbacks are fired even if the original browser transition end events are
* canceled
*/
onEntering: React.PropTypes.func,
duration: React.PropTypes.number,

/**
* A Callback fired after the component has faded in.
* Callback fired before the component fades in
*/
onEntered: React.PropTypes.func,

onEnter: React.PropTypes.func,
/**
* A Callback fired before the component starts to fade out.
* Callback fired after the component starts to fade in
*/
onExit: React.PropTypes.func,

onEntering: React.PropTypes.func,
/**
* A Callback fired immediately after the component has started to faded out.
* Callback fired after the has component faded in
*/
onExiting: React.PropTypes.func,

onEntered: React.PropTypes.func,
/**
* A Callback fired after the component has faded out.
* Callback fired before the component fades out
*/
onExited: React.PropTypes.func,


onExit: React.PropTypes.func,
/**
* Specify whether the transitioning component should be unmounted (removed from the DOM) once the exit animation finishes.
* Callback fired after the component starts to fade out
*/
unmountOnExit: React.PropTypes.bool,

onExiting: React.PropTypes.func,
/**
* Specify whether the component should fade in or out when it mounts.
* Callback fired after the component has faded out
*/
transitionAppear: React.PropTypes.bool

onExited: React.PropTypes.func
};

Fade.defaultProps = {
in: false,
in: false,
duration: 300,
dimension: 'height',
transitionAppear: false,
unmountOnExit: false
unmountOnExit: false,
transitionAppear: false
};

export default Fade;
Expand Down
97 changes: 49 additions & 48 deletions src/Overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,24 @@ import CustomPropTypes from './utils/CustomPropTypes';
import Fade from './Fade';
import classNames from 'classnames';


class Overlay extends React.Component {

constructor(props, context){
constructor(props, context) {
super(props, context);

this.state = { exited: false };
this.state = {exited: !props.show};
this.onHiddenListener = this.handleHidden.bind(this);
}

componentWillReceiveProps(nextProps) {
let state = {};

if ( !nextProps.show && this.props.show ){
state.exiting = true;
}

if (nextProps.show) {
state = { exited: false, exiting: false };
this.setState({exited: false});
} else if (!nextProps.animation) {
// Otherwise let handleHidden take care of marking exited.
this.setState({exited: true});
}

this.setState(state);
}

render(){
render() {
let {
container
, containerPadding
Expand All @@ -42,56 +35,64 @@ class Overlay extends React.Component {
, animation: Transition
, ...props } = this.props;

let child = null;

if ( Transition === true ){
if (Transition === true) {
Transition = Fade;
}

if (props.show || (Transition && this.state.exiting && !this.state.exited)) {
// Don't un-render the overlay while it's transitioning out.
const mountOverlay = props.show || (Transition && !this.state.exited);
if (!mountOverlay) {
// Don't bother showing anything if we don't have to.
return null;
}

child = children;
let child = children;

// Position the child before the animation to avoid `null` DOM nodes
// Position is be inner-most because it adds inline styles into the child,
// which the other wrappers don't forward correctly.
child = (
<Position {...{container, containerPadding, target, placement}}>
{child}
</Position>
);

if (Transition) {
// This animates the child node by injecting props, so it must precede
// anything that adds a wrapping div.
child = (
<Position {...{ container, containerPadding, target, placement }}>
{ child }
</Position>
<Transition
in={props.show}
transitionAppear
onExited={this.onHiddenListener}
>
{child}
</Transition>
);
} else {
child = cloneElement(
child,
{className: classNames('in', child.className)}
);

child = Transition
? (
<Transition
unmountOnExit
in={props.show}
transitionAppear={props.show}
onExited={this.onHiddenListener}
>
{ child }
</Transition>
)
: cloneElement(child, { className: classNames('in', child.className) });

//Adds a wrapping div so it cannot be before Transition
if (rootClose) {
child = (
<RootCloseWrapper onRootClose={props.onHide}>
{ child }
</RootCloseWrapper>
);
}
}

// This goes after everything else because it adds a wrapping div.
if (rootClose) {
child = (
<RootCloseWrapper onRootClose={props.onHide}>
{child}
</RootCloseWrapper>
);
}

return (
<Portal container={container}>
{ child }
{child}
</Portal>
);
}

handleHidden(){
this.setState({ exited: true, exiting: false });
handleHidden() {
this.setState({exited: true});
}
}

Expand Down
Loading

0 comments on commit 1160c50

Please sign in to comment.