diff --git a/src/dialog.jsx b/src/dialog.jsx
index 57be10775f86fb..b0f0a2cc5fccb5 100644
--- a/src/dialog.jsx
+++ b/src/dialog.jsx
@@ -512,6 +512,37 @@ const Dialog = React.createClass({
};
},
+ getInitialState() {
+ return {
+ open: this.props.open,
+ closing: false,
+ };
+ },
+
+ componentWillReceiveProps(nextProps, nextContext) {
+ let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
+
+ if (nextProps.open !== this.state.open) {
+ if (nextProps.open) {
+ this.setState({
+ open: true,
+ closing: false,
+ muiTheme: newMuiTheme,
+ });
+ } else {
+ this.setState({closing: true});
+ this._timeout = setTimeout(() => {
+ if (this.isMounted()) {
+ this.setState({
+ open: false,
+ muiTheme: newMuiTheme,
+ });
+ }
+ }, 500);
+ }
+ }
+ },
+
renderLayer() {
return (
@@ -520,7 +551,7 @@ const Dialog = React.createClass({
render() {
return (
-
+
);
},
diff --git a/src/popover/popover-animation-from-top.jsx b/src/popover/popover-animation-from-top.jsx
index 339f2857d4364d..d9e338a455d397 100644
--- a/src/popover/popover-animation-from-top.jsx
+++ b/src/popover/popover-animation-from-top.jsx
@@ -23,7 +23,7 @@ function getStyles(props, state) {
opacity: open ? 1 : 0,
transform: open ? 'scaleY(1)' : 'scaleY(0)',
transformOrigin: `${horizontal} ${targetOrigin.vertical}`,
- position: 'fixed',
+ position: 'absolute',
zIndex: zIndex.popover,
transition: Transitions.easeOut('450ms', ['transform', 'opacity']),
maxHeight: '100%',
diff --git a/src/popover/popover-default-animation.jsx b/src/popover/popover-default-animation.jsx
index 86a8bf325a0017..5d9b526dd1dcaf 100644
--- a/src/popover/popover-default-animation.jsx
+++ b/src/popover/popover-default-animation.jsx
@@ -23,7 +23,7 @@ function getStyles(props, state) {
opacity: open ? 1 : 0,
transform: open ? 'scale(1, 1)' : 'scale(0, 0)',
transformOrigin: `${horizontal} ${targetOrigin.vertical}`,
- position: 'fixed',
+ position: 'absolute',
zIndex: zIndex.popover,
transition: Transitions.easeOut('250ms', ['transform', 'opacity']),
maxHeight: '100%',
diff --git a/src/popover/popover.jsx b/src/popover/popover.jsx
index 604f6223c5ed5e..9b40939ea24865 100644
--- a/src/popover/popover.jsx
+++ b/src/popover/popover.jsx
@@ -243,8 +243,8 @@ const Popover = React.createClass({
const a = {
top: rect.top,
left: rect.left,
- width: el.offsetWidth,
- height: el.offsetHeight,
+ width: rect.width,
+ height: rect.height,
};
a.right = rect.right || a.left + a.width;
diff --git a/src/render-to-layer.jsx b/src/render-to-layer.jsx
index 460b5108fc863a..a532a3179d19e8 100644
--- a/src/render-to-layer.jsx
+++ b/src/render-to-layer.jsx
@@ -2,6 +2,8 @@ import React from 'react';
import ReactDOM from 'react-dom';
import Dom from './utils/dom';
import getMuiTheme from './styles/getMuiTheme';
+import WindowListenable from './mixins/window-listenable';
+import throttle from 'lodash.throttle';
// heavily inspired by https://github.com/Khan/react-components/blob/master/js/layered-component-mixin.jsx
const RenderToLayer = React.createClass({
@@ -22,6 +24,10 @@ const RenderToLayer = React.createClass({
muiTheme: React.PropTypes.object,
},
+ mixins: [
+ WindowListenable,
+ ],
+
getDefaultProps() {
return {
useLayerForClickAway: true,
@@ -29,6 +35,7 @@ const RenderToLayer = React.createClass({
},
getInitialState() {
+ this._renderLayerThrottled = throttle(this._renderLayer, 100);
return {
muiTheme: this.context.muiTheme || getMuiTheme(),
};
@@ -61,6 +68,11 @@ const RenderToLayer = React.createClass({
this._unrenderLayer();
},
+ windowListeners: {
+ resize: '_renderLayerThrottled',
+ scroll: '_renderLayerThrottled',
+ },
+
onClickAway(event) {
if (event.defaultPrevented) {
return;
@@ -113,16 +125,12 @@ const RenderToLayer = React.createClass({
if (open) {
if (!this._layer) {
this._layer = document.createElement('div');
+ this._layer.style.position = 'absolute';
document.body.appendChild(this._layer);
if (this.props.useLayerForClickAway) {
this._layer.addEventListener('touchstart', this.onClickAway);
this._layer.addEventListener('click', this.onClickAway);
- this._layer.style.position = 'fixed';
- this._layer.style.top = 0;
- this._layer.style.bottom = 0;
- this._layer.style.left = 0;
- this._layer.style.right = 0;
this._layer.style.zIndex = this.state.muiTheme.zIndex.layer;
} else {
setTimeout(() => {
@@ -131,7 +139,15 @@ const RenderToLayer = React.createClass({
}, 0);
}
}
-
+ const {documentElement, body} = document;
+ const top = window.pageYOffset || documentElement.scrollTop || body.scrollTop || 0;
+ const left = window.pageXOffset || documentElement.scrollLeft || body.scrollLeft || 0;
+
+ this._layer.style.top = `${top}px`;
+ this._layer.style.height = `${body.clientHeight}px`;
+ this._layer.style.left = `${left}px`;
+ this._layer.style.width = `${body.clientWidth}px`;
+
// By calling this method in componentDidMount() and
// componentDidUpdate(), you're effectively creating a "wormhole" that
// funnels React's hierarchical updates through to a DOM node on an