diff --git a/packages/material-ui/src/Popper/Popper.js b/packages/material-ui/src/Popper/Popper.js index 80f5f99096f2fe..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 window !== '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 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({