diff --git a/docs/README.md b/docs/README.md index e05c0d2a..e63ac121 100644 --- a/docs/README.md +++ b/docs/README.md @@ -79,6 +79,11 @@ import ReactModal from 'react-modal'; Boolean indicating if the overlay should close the modal */ shouldCloseOnOverlayClick={true} + /* + Boolean indicating if pressing the esc key should close the modal + Note: By disabling the esc key from closing the modal you may introduce an accessibility issue. + */ + shouldCloseOnEsc={true} /* String indicating the role of the modal, allowing the 'dialog' role to be applied if desired. */ diff --git a/specs/Modal.events.spec.js b/specs/Modal.events.spec.js index c12d7016..4c3af5fd 100644 --- a/specs/Modal.events.spec.js +++ b/specs/Modal.events.spec.js @@ -42,18 +42,35 @@ export default () => { document.activeElement.should.be.eql(content); }); - it("should close on Esc key event", () => { - const requestCloseCallback = sinon.spy(); - const modal = renderModal({ - isOpen: true, - shouldCloseOnOverlayClick: true, - onRequestClose: requestCloseCallback + describe("shouldCloseOnEsc", () => { + context("when true", () => { + it("should close on Esc key event", () => { + const requestCloseCallback = sinon.spy(); + const modal = renderModal({ + isOpen: true, + shouldCloseOnEsc: true, + onRequestClose: requestCloseCallback + }); + escKeyDown(mcontent(modal)); + requestCloseCallback.called.should.be.ok(); + // Check if event is passed to onRequestClose callback. + const event = requestCloseCallback.getCall(0).args[0]; + event.should.be.ok(); + }); + }); + + context("when false", () => { + it("should not close on Esc key event", () => { + const requestCloseCallback = sinon.spy(); + const modal = renderModal({ + isOpen: true, + shouldCloseOnEsc: false, + onRequestClose: requestCloseCallback + }); + escKeyDown(mcontent(modal)); + requestCloseCallback.called.should.be.false; + }); }); - escKeyDown(mcontent(modal)); - requestCloseCallback.called.should.be.ok(); - // Check if event is passed to onRequestClose callback. - const ev = requestCloseCallback.getCall(0).args[0]; - ev.should.be.ok(); }); describe("shouldCloseOnoverlayClick", () => { diff --git a/src/components/Modal.js b/src/components/Modal.js index 104d83a0..8301e8af 100644 --- a/src/components/Modal.js +++ b/src/components/Modal.js @@ -43,7 +43,8 @@ export default class Modal extends Component { parentSelector: PropTypes.func, aria: PropTypes.object, role: PropTypes.string, - contentLabel: PropTypes.string + contentLabel: PropTypes.string, + shouldCloseOnEsc: PropTypes.bool }; /* eslint-enable react/no-unused-prop-types */ @@ -54,6 +55,7 @@ export default class Modal extends Component { ariaHideApp: true, closeTimeoutMS: 0, shouldFocusAfterRender: true, + shouldCloseOnEsc: true, shouldCloseOnOverlayClick: true, parentSelector() { return document.body; diff --git a/src/components/ModalPortal.js b/src/components/ModalPortal.js index 5aeb7b5c..86a924ae 100644 --- a/src/components/ModalPortal.js +++ b/src/components/ModalPortal.js @@ -47,7 +47,8 @@ export default class ModalPortal extends Component { role: PropTypes.string, contentLabel: PropTypes.string, aria: PropTypes.object, - children: PropTypes.node + children: PropTypes.node, + shouldCloseOnEsc: PropTypes.bool }; constructor(props) { @@ -195,7 +196,8 @@ export default class ModalPortal extends Component { if (event.keyCode === TAB_KEY) { scopeTab(this.content, event); } - if (event.keyCode === ESC_KEY) { + + if (this.props.shouldCloseOnEsc && event.keyCode === ESC_KEY) { event.preventDefault(); this.requestClose(event); }