From 46e98b33c70e436b88ec33fa97594ee1240892eb Mon Sep 17 00:00:00 2001 From: Quentin Herzig Date: Fri, 15 Nov 2019 10:01:08 +0100 Subject: [PATCH 1/2] Use document instead of window for SSR --- packages/material-ui/src/Popper/Popper.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/material-ui/src/Popper/Popper.js b/packages/material-ui/src/Popper/Popper.js index 80f5f99096f2fe..2adc901487a7e8 100644 --- a/packages/material-ui/src/Popper/Popper.js +++ b/packages/material-ui/src/Popper/Popper.js @@ -13,7 +13,7 @@ import ownerWindow from '../utils/ownerWindow'; * @param {string} placement */ function flipPlacement(placement) { - const direction = (typeof window !== 'undefined' && document.body.getAttribute('dir')) || 'ltr'; + const direction = (typeof document !== 'undefined' && document.body.getAttribute('dir')) || 'ltr'; if (direction !== 'rtl') { return placement; @@ -126,11 +126,11 @@ const Popper = React.forwardRef(function Popper(props, ref) { ...(disablePortal ? {} : { - // It's using scrollParent by default, we can use the viewport when using a portal. - preventOverflow: { - boundariesElement: 'window', - }, - }), + // It's using scrollParent by default, we can use the viewport when using a portal. + preventOverflow: { + boundariesElement: 'window', + }, + }), ...modifiers, ...popperOptions.modifiers, }, From f4aa2aa07384fdf300ab4db1efe4c8d856a0753b Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sat, 16 Nov 2019 01:24:04 +0100 Subject: [PATCH 2/2] use context --- packages/material-ui/src/Popper/Popper.js | 24 ++++---- .../material-ui/src/Popper/Popper.test.js | 57 ++++++++++--------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/packages/material-ui/src/Popper/Popper.js b/packages/material-ui/src/Popper/Popper.js index 2adc901487a7e8..d2542f49c19e63 100644 --- a/packages/material-ui/src/Popper/Popper.js +++ b/packages/material-ui/src/Popper/Popper.js @@ -2,20 +2,17 @@ import React from 'react'; import PropTypes from 'prop-types'; import PopperJS from 'popper.js'; import { chainPropTypes, refType } from '@material-ui/utils'; +import { useTheme } from '@material-ui/styles'; import Portal from '../Portal'; import createChainedFunction from '../utils/createChainedFunction'; import setRef from '../utils/setRef'; import useForkRef from '../utils/useForkRef'; import ownerWindow from '../utils/ownerWindow'; -/** - * Flips placement if in - * @param {string} placement - */ -function flipPlacement(placement) { - const direction = (typeof document !== 'undefined' && document.body.getAttribute('dir')) || 'ltr'; +function flipPlacement(placement, theme) { + const direction = (theme && theme.direction) || 'ltr'; - if (direction !== 'rtl') { + if (direction === 'ltr') { return placement; } @@ -72,7 +69,8 @@ const Popper = React.forwardRef(function Popper(props, ref) { const [exited, setExited] = React.useState(true); - const rtlPlacement = flipPlacement(initialPlacement); + const theme = useTheme(); + const rtlPlacement = flipPlacement(initialPlacement, theme); /** * placement initialized from prop but can change during lifetime if modifiers.flip. * modifiers.flip is essentially a flip for controlled/uncontrolled behavior @@ -126,11 +124,11 @@ const Popper = React.forwardRef(function Popper(props, ref) { ...(disablePortal ? {} : { - // It's using scrollParent by default, we can use the viewport when using a portal. - preventOverflow: { - boundariesElement: 'window', - }, - }), + // It's using scrollParent by default, we can use the viewport when using a portal. + preventOverflow: { + boundariesElement: 'window', + }, + }), ...modifiers, ...popperOptions.modifiers, }, diff --git a/packages/material-ui/src/Popper/Popper.test.js b/packages/material-ui/src/Popper/Popper.test.js index 39002ee20e1007..b89cad3fd977a9 100644 --- a/packages/material-ui/src/Popper/Popper.test.js +++ b/packages/material-ui/src/Popper/Popper.test.js @@ -3,6 +3,7 @@ import { assert, expect } from 'chai'; import { spy, useFakeTimers } from 'sinon'; import PropTypes from 'prop-types'; import { createMount } from '@material-ui/core/test-utils'; +import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles'; import describeConformance from '@material-ui/core/test-utils/describeConformance'; import { createClientRender } from 'test/utils/createClientRender'; import consoleErrorMock from 'test/utils/consoleErrorMock'; @@ -12,6 +13,7 @@ import Popper from './Popper'; describe('', () => { let mount; + let rtlTheme; const render = createClientRender({ strict: true }); const defaultProps = { anchorEl: () => document.createElement('svg'), @@ -21,6 +23,9 @@ describe('', () => { before(() => { mount = createMount({ strict: true }); + rtlTheme = createMuiTheme({ + direction: 'rtl', + }); }); after(() => { @@ -40,23 +45,17 @@ describe('', () => { })); describe('prop: placement', () => { - before(() => { - document.body.setAttribute('dir', 'rtl'); - }); - - after(() => { - document.body.removeAttribute('dir'); - }); - it('should have top placement', () => { const renderSpy = spy(); mount( - - {({ placement }) => { - renderSpy(placement); - return null; - }} - , + + + {({ placement }) => { + renderSpy(placement); + return null; + }} + + , ); assert.strictEqual(renderSpy.callCount, 2); // 2 for strict mode assert.strictEqual(renderSpy.args[0][0], 'top'); @@ -87,12 +86,15 @@ describe('', () => { it(`should flip ${test.in} when direction=rtl is used`, () => { const renderSpy = spy(); mount( - - {({ placement }) => { - renderSpy(placement); - return null; - }} - , + + + {({ placement }) => { + renderSpy(placement); + return null; + }} + + , + , ); assert.strictEqual(renderSpy.callCount, 2); assert.strictEqual(renderSpy.args[0][0], test.out); @@ -103,12 +105,15 @@ describe('', () => { const renderSpy = spy(); const popperRef = React.createRef(); render( - - {({ placement }) => { - renderSpy(placement); - return null; - }} - , + + + {({ placement }) => { + renderSpy(placement); + return null; + }} + + , + , ); expect(renderSpy.args).to.deep.equal([['bottom'], ['bottom']]); popperRef.current.options.onUpdate({