diff --git a/lib/components/ModalPortal.js b/lib/components/ModalPortal.js index 30075d6a..22060a1b 100644 --- a/lib/components/ModalPortal.js +++ b/lib/components/ModalPortal.js @@ -99,7 +99,10 @@ var ModalPortal = module.exports = React.createClass({ }, focusContent: function() { - this.refs.content.focus(); + // Don't steal focus from inner elements + if (!this.contentHasFocus()) { + this.refs.content.focus(); + } }, closeWithTimeout: function() { @@ -166,6 +169,10 @@ var ModalPortal = module.exports = React.createClass({ return !this.props.isOpen && !this.state.beforeClose; }, + contentHasFocus() { + return document.activeElement === this.refs.content || this.refs.content.contains(document.activeElement); + }, + buildClassName: function(which, additional) { var className = CLASS_NAMES[which].base; if (this.state.afterOpen) diff --git a/specs/Modal.spec.js b/specs/Modal.spec.js index 6cee0450..98b74016 100644 --- a/specs/Modal.spec.js +++ b/specs/Modal.spec.js @@ -86,6 +86,14 @@ describe('Modal', function () { }); }); + it('does not focus the modal content when a descendent is already focused', function() { + var input = React.DOM.input({ className: 'focus_input', ref: function(el) { el && el.focus(); } }); + renderModal({isOpen: true}, input, function () { + strictEqual(document.activeElement, document.querySelector('.focus_input')); + unmountModal(); + }); + }); + it('handles case when child has no tabbable elements', function() { var component = renderModal({isOpen: true}, 'hello'); assert.doesNotThrow(function() {