From ff0a7f5b69ac6dd68e79e2c0968ccae6e1bebdec Mon Sep 17 00:00:00 2001 From: Cameron Ackerman Date: Thu, 7 Feb 2019 08:33:51 -0800 Subject: [PATCH] [added] a preventScroll prop to allows the modal to optionally use a preventScroll flag when focusing the element that had focus prior to display of the modal. --- docs/index.md | 11 ++++++++--- specs/Modal.spec.js | 1 + src/components/Modal.js | 2 ++ src/components/ModalPortal.js | 3 ++- src/helpers/focusManager.js | 4 ++-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/index.md b/docs/index.md index c2f2b006..d3ddf032 100644 --- a/docs/index.md +++ b/docs/index.md @@ -79,9 +79,9 @@ import ReactModal from 'react-modal'; bodyOpenClassName={ "ReactModal__Body--open" - /* String className to be applied to the document.body + /* String className to be applied to the document.body (must be a constant string). - This attribute when set as `null` doesn't add any class + This attribute when set as `null` doesn't add any class to document.body. See the `Styles` section for more details. */} @@ -121,6 +121,11 @@ import ReactModal from 'react-modal'; to be applied if desired. This attribute is `dialog` by default. */} + preventScroll={ + false + /* Boolean indicating if the modal should use the preventScroll flag when + restoring focus to the element that had focus prior to its display. */} + parentSelector={ () => document.body /* Function that will be called to get the parent element @@ -136,7 +141,7 @@ import ReactModal from 'react-modal'; data={ { background: "green" } /* Additional data attributes (optional). */} - + testId={ "" /* String testId that renders a data-testid attribute in the DOM, diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js index 2600e608..4bd1fe2d 100644 --- a/specs/Modal.spec.js +++ b/specs/Modal.spec.js @@ -51,6 +51,7 @@ export default () => { props.closeTimeoutMS.should.be.eql(0); props.shouldFocusAfterRender.should.be.ok(); props.shouldCloseOnOverlayClick.should.be.ok(); + props.preventScroll.should.be.false(); ReactDOM.unmountComponentAtNode(node); ariaAppHider.resetForTesting(); Modal.setAppElement(document.body); // restore default diff --git a/src/components/Modal.js b/src/components/Modal.js index 0ef0b618..41f1218d 100644 --- a/src/components/Modal.js +++ b/src/components/Modal.js @@ -60,6 +60,7 @@ class Modal extends Component { shouldFocusAfterRender: PropTypes.bool, shouldCloseOnOverlayClick: PropTypes.bool, shouldReturnFocusAfterClose: PropTypes.bool, + preventScroll: PropTypes.bool, parentSelector: PropTypes.func, aria: PropTypes.object, data: PropTypes.object, @@ -82,6 +83,7 @@ class Modal extends Component { shouldCloseOnEsc: true, shouldCloseOnOverlayClick: true, shouldReturnFocusAfterClose: true, + preventScroll: false, parentSelector: () => document.body }; diff --git a/src/components/ModalPortal.js b/src/components/ModalPortal.js index 5414c547..17768eae 100644 --- a/src/components/ModalPortal.js +++ b/src/components/ModalPortal.js @@ -51,6 +51,7 @@ export default class ModalPortal extends Component { shouldFocusAfterRender: PropTypes.bool, shouldCloseOnOverlayClick: PropTypes.bool, shouldReturnFocusAfterClose: PropTypes.bool, + preventScroll: PropTypes.bool, role: PropTypes.string, contentLabel: PropTypes.string, aria: PropTypes.object, @@ -185,7 +186,7 @@ export default class ModalPortal extends Component { if (this.props.shouldFocusAfterRender) { if (this.props.shouldReturnFocusAfterClose) { - focusManager.returnFocus(); + focusManager.returnFocus(this.props.preventScroll); focusManager.teardownScopedFocus(); } else { focusManager.popWithoutFocus(); diff --git a/src/helpers/focusManager.js b/src/helpers/focusManager.js index 0a8accd8..96fbc349 100644 --- a/src/helpers/focusManager.js +++ b/src/helpers/focusManager.js @@ -34,12 +34,12 @@ export function markForFocusLater() { } /* eslint-disable no-console */ -export function returnFocus() { +export function returnFocus(preventScroll = false) { let toFocus = null; try { if (focusLaterElements.length !== 0) { toFocus = focusLaterElements.pop(); - toFocus.focus(); + toFocus.focus({ preventScroll }); } return; } catch (e) {