From 49a163477760e4ef9d9b4c3a2cfa08fb753dbd98 Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Fri, 26 Jan 2018 11:41:05 -0800 Subject: [PATCH 1/4] Popover should default to use anchorEl's parent body --- src/Popover/Popover.js | 9 ++++++- src/Popover/Popover.spec.js | 49 ++++++++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Popover/Popover.js b/src/Popover/Popover.js index 88fc4c61789624..66cd60a38feafc 100644 --- a/src/Popover/Popover.js +++ b/src/Popover/Popover.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import warning from 'warning'; import contains from 'dom-helpers/query/contains'; +import ownerDocument from 'dom-helpers/ownerDocument'; import debounce from 'lodash/debounce'; import EventListener from 'react-event-listener'; import withStyles from '../styles/withStyles'; @@ -247,6 +248,7 @@ class Popover extends React.Component { anchorReference, children, classes, + container: containerProp, elevation, getContentAnchorEl, marginThreshold, @@ -266,6 +268,11 @@ class Popover extends React.Component { ...other } = this.props; + // If the container prop is provided, use that + // If the anchorEl prop is provided, use its parent body element as the container + // If neither are provided let the Modal take care of choosing the container + const container = containerProp || (anchorEl ? ownerDocument(anchorEl).body : undefined); + const transitionProps = {}; // The provided transition might not support the auto timeout value. @@ -274,7 +281,7 @@ class Popover extends React.Component { } return ( - + ', () => { let expectPopover; before(() => { - openPopover = anchorOrigin => { + openPopover = (anchorOrigin, renderShallow) => { return new Promise(resolve => { if (!anchorEl) { anchorEl = window.document.createElement('div'); @@ -314,7 +314,8 @@ describe('', () => { left: '100px', }); window.document.body.appendChild(anchorEl); - wrapper = mount( + + const component = ( ', () => { }} >
- , + ); + wrapper = renderShallow ? shallow(component) : mount(component); wrapper.setProps({ open: true }); + + if (renderShallow) { + resolve(); + } }); }; @@ -408,6 +414,43 @@ describe('', () => { expectPopover(expectedTop, expectedLeft); }); }); + + it('should pass through container prop to Modal if both container and anchorEl props are provided', () => { + const container = {}; + const wrapper = shallow(); + assert.strictEqual( + wrapper + .dive() + .find('Modal') + .props().container, + container, + 'should pass through container prop if both container and anchorEl props are provided', + ); + }); + + it("should use anchorEl's parent body as Modal container if container prop not provided", () => { + return openPopover(undefined, true).then(() => { + assert.strictEqual( + wrapper + .dive() + .find('Modal') + .props().container, + window.document.body, + "should use anchorEl's parent body as Modal container", + ); + }); + }); + + it('should not pass a container prop to Modal if neither of container or anchorEl props are provided', () => { + const wrapper = shallow(); + assert.isUndefined( + wrapper + .dive() + .find('Modal') + .props().container, + 'should pass through container prop if both container and anchorEl props are provided', + ); + }); }); describe('positioning on a manual position', () => { From 41d14691f8667f5998636ab3b4d02f683a77679c Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Fri, 26 Jan 2018 11:45:39 -0800 Subject: [PATCH 2/4] Fix assertion error message --- src/Popover/Popover.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Popover/Popover.spec.js b/src/Popover/Popover.spec.js index 5a63255d5d17dd..40b360c5ad3d90 100644 --- a/src/Popover/Popover.spec.js +++ b/src/Popover/Popover.spec.js @@ -442,13 +442,13 @@ describe('', () => { }); it('should not pass a container prop to Modal if neither of container or anchorEl props are provided', () => { - const wrapper = shallow(); + const wrapper = shallow(); assert.isUndefined( wrapper .dive() .find('Modal') .props().container, - 'should pass through container prop if both container and anchorEl props are provided', + 'should not pass a container prop if neither container or anchorEl are provided', ); }); }); From ed6d54ec2d47e442a365696404fc8cff039a8541 Mon Sep 17 00:00:00 2001 From: Ian Schmitz Date: Fri, 26 Jan 2018 12:10:22 -0800 Subject: [PATCH 3/4] Fix lint errors --- src/Popover/Popover.js | 5 +++++ src/Popover/Popover.spec.js | 14 +++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Popover/Popover.js b/src/Popover/Popover.js index 66cd60a38feafc..87b5e2acbd051b 100644 --- a/src/Popover/Popover.js +++ b/src/Popover/Popover.js @@ -366,6 +366,11 @@ Popover.propTypes = { * Useful to extend the style applied to components. */ classes: PropTypes.object.isRequired, + /** + * A node, component instance, or function that returns either. + * The `container` will passed to the Modal component. + */ + container: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), /** * The elevation of the popover. */ diff --git a/src/Popover/Popover.spec.js b/src/Popover/Popover.spec.js index 40b360c5ad3d90..e62f1d7c9e8524 100644 --- a/src/Popover/Popover.spec.js +++ b/src/Popover/Popover.spec.js @@ -415,11 +415,11 @@ describe('', () => { }); }); - it('should pass through container prop to Modal if both container and anchorEl props are provided', () => { + it('should pass through container prop if container and anchorEl props are provided', () => { const container = {}; - const wrapper = shallow(); + const shallowWrapper = shallow(); assert.strictEqual( - wrapper + shallowWrapper .dive() .find('Modal') .props().container, @@ -428,7 +428,7 @@ describe('', () => { ); }); - it("should use anchorEl's parent body as Modal container if container prop not provided", () => { + it("should use anchorEl's parent body as container if container prop not provided", () => { return openPopover(undefined, true).then(() => { assert.strictEqual( wrapper @@ -441,10 +441,10 @@ describe('', () => { }); }); - it('should not pass a container prop to Modal if neither of container or anchorEl props are provided', () => { - const wrapper = shallow(); + it('should not pass container to Modal if container or anchorEl props are notprovided', () => { + const shallowWrapper = shallow(); assert.isUndefined( - wrapper + shallowWrapper .dive() .find('Modal') .props().container, From 8a04390b37604379654cb7d2c3f67b06b2145b42 Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sat, 27 Jan 2018 00:16:40 +0100 Subject: [PATCH 4/4] green --- .size-limit | 2 +- docs/src/pages/customization/themes.md | 2 +- pages/api/popover.md | 1 + pages/api/portal.md | 2 +- src/Input/Input.spec.js | 2 +- src/Popover/Popover.js | 3 ++- src/Popover/Popover.spec.js | 3 ++- src/Portal/Portal.js | 2 +- 8 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.size-limit b/.size-limit index bf5ae575d6e96e..18a742fdffc583 100644 --- a/.size-limit +++ b/.size-limit @@ -7,7 +7,7 @@ { "name": "The size of the whole library.", "path": "build/index.js", - "limit": "96.3 KB" + "limit": "96.5 KB" }, { "name": "The main bundle of the documentation", diff --git a/docs/src/pages/customization/themes.md b/docs/src/pages/customization/themes.md index 2951f7399facc2..ea475f3a229e8e 100644 --- a/docs/src/pages/customization/themes.md +++ b/docs/src/pages/customization/themes.md @@ -79,7 +79,7 @@ palette: { }, ``` -This example illustrates how you could recreate the the default palette values: +This example illustrates how you could recreate the default palette values: ```jsx import { createMuiTheme } from 'material-ui/styles'; diff --git a/pages/api/popover.md b/pages/api/popover.md index 04c43001ebc687..07343f1ad65b8d 100644 --- a/pages/api/popover.md +++ b/pages/api/popover.md @@ -19,6 +19,7 @@ filename: /src/Popover/Popover.js | anchorReference | enum: 'anchorEl' |
 'anchorPosition'
| 'anchorEl' | | | children | node | | The content of the component. | | classes | object | | Useful to extend the style applied to components. | +| container | union: object |
 func
| | A node, component instance, or function that returns either. The `container` will passed to the Modal component. By default, it's using the body of the anchorEl's top-level document object, so it's simply `document.body` most of the time. | | elevation | number | 8 | The elevation of the popover. | | getContentAnchorEl | func | | This function is called in order to retrieve the content anchor element. It's the opposite of the `anchorEl` property. The content anchor element should be an element inside the popover. It's used to correctly scroll and set the position of the popover. The positioning strategy tries to make the content anchor element just above the anchor element. | | marginThreshold | number | 16 | Specifies how close to the edge of the window the popover can appear. | diff --git a/pages/api/portal.md b/pages/api/portal.md index e381a9a84f7f3b..324207896660ea 100644 --- a/pages/api/portal.md +++ b/pages/api/portal.md @@ -16,7 +16,7 @@ and take the control of our destiny. | Name | Type | Default | Description | |:-----|:-----|:--------|:------------| | children * | node | | The children to render into the `container`. | -| container | union: object |
 func
| | A node, component instance, or function that returns either. The `container` will have the portal children appended to it. By default, it's using the body of the the top-level document object, so it's simply `document.body` most of the time. | +| container | union: object |
 func
| | A node, component instance, or function that returns either. The `container` will have the portal children appended to it. By default, it's using the body of the top-level document object, so it's simply `document.body` most of the time. | | onRendered | func | | Callback fired once the children has been mounted into the `container`. | Any other properties supplied will be [spread to the root element](/guides/api#spread). diff --git a/src/Input/Input.spec.js b/src/Input/Input.spec.js index c52451c9585427..902454527d5344 100644 --- a/src/Input/Input.spec.js +++ b/src/Input/Input.spec.js @@ -95,7 +95,7 @@ describe('', () => { }); // IE11 bug - it('should not respond the the focus event when disabled', () => { + it('should not respond the focus event when disabled', () => { const wrapper = shallow(); const instance = wrapper.instance(); const event = { diff --git a/src/Popover/Popover.js b/src/Popover/Popover.js index 87b5e2acbd051b..50982dadcc2b86 100644 --- a/src/Popover/Popover.js +++ b/src/Popover/Popover.js @@ -274,7 +274,6 @@ class Popover extends React.Component { const container = containerProp || (anchorEl ? ownerDocument(anchorEl).body : undefined); const transitionProps = {}; - // The provided transition might not support the auto timeout value. if (TransitionProp === Grow) { transitionProps.timeout = transitionDuration; @@ -369,6 +368,8 @@ Popover.propTypes = { /** * A node, component instance, or function that returns either. * The `container` will passed to the Modal component. + * By default, it's using the body of the anchorEl's top-level document object, + * so it's simply `document.body` most of the time. */ container: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), /** diff --git a/src/Popover/Popover.spec.js b/src/Popover/Popover.spec.js index e62f1d7c9e8524..68951fcbb0b324 100644 --- a/src/Popover/Popover.spec.js +++ b/src/Popover/Popover.spec.js @@ -443,11 +443,12 @@ describe('', () => { it('should not pass container to Modal if container or anchorEl props are notprovided', () => { const shallowWrapper = shallow(); - assert.isUndefined( + assert.strictEqual( shallowWrapper .dive() .find('Modal') .props().container, + undefined, 'should not pass a container prop if neither container or anchorEl are provided', ); }); diff --git a/src/Portal/Portal.js b/src/Portal/Portal.js index cbdccdf7648890..3cff76ceadeada 100644 --- a/src/Portal/Portal.js +++ b/src/Portal/Portal.js @@ -61,7 +61,7 @@ Portal.propTypes = { /** * A node, component instance, or function that returns either. * The `container` will have the portal children appended to it. - * By default, it's using the body of the the top-level document object, + * By default, it's using the body of the top-level document object, * so it's simply `document.body` most of the time. */ container: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),