From 2028f440070ef039068942c375a017fdc2c8d7aa Mon Sep 17 00:00:00 2001 From: Clay Diffrient Date: Mon, 11 Jul 2016 15:03:02 -0600 Subject: [PATCH] [added] Add elementToFocus prop This makes it so if you provide elementAfterFocus then that particular element will be focused after the component renders instead of the content of the tray. This is handy to set focus to a close button or some other arbitrary element within the content. --- lib/components/Tray.js | 3 ++- lib/components/TrayPortal.js | 15 +++++++++++++-- lib/components/__tests__/Tray-test.js | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/components/Tray.js b/lib/components/Tray.js index f3440c2..c566fd7 100644 --- a/lib/components/Tray.js +++ b/lib/components/Tray.js @@ -12,7 +12,8 @@ export default React.createClass({ onOpen: React.PropTypes.func, closeTimeoutMS: React.PropTypes.number, closeOnBlur: React.PropTypes.bool, - maintainFocus: React.PropTypes.bool + maintainFocus: React.PropTypes.bool, + elementToFocus: React.PropTypes.string }, getDefaultProps() { diff --git a/lib/components/TrayPortal.js b/lib/components/TrayPortal.js index 05b034e..81524af 100644 --- a/lib/components/TrayPortal.js +++ b/lib/components/TrayPortal.js @@ -58,7 +58,8 @@ export default React.createClass({ closeOnBlur: PropTypes.bool, closeTimeoutMS: PropTypes.number, children: PropTypes.any, - maintainFocus: PropTypes.bool + maintainFocus: PropTypes.bool, + elementToFocus: PropTypes.string }, getInitialState() { @@ -86,7 +87,11 @@ export default React.createClass({ componentDidUpdate() { if (this.focusAfterRender) { - this.focusContent(); + if (this.props.elementToFocus) { + this.focusSelector(this.props.elementToFocus); + } else { + this.focusContent(); + } this.setFocusAfterRender(false); } }, @@ -99,6 +104,12 @@ export default React.createClass({ this.refs.content.focus(); }, + focusSelector(querySelectorToUse) { + const el = document.querySelectorAll(querySelectorToUse); + const element = (el.length) ? el[0] : el; + element.focus(); + }, + handleOverlayClick(e) { if (!isChild(this.refs.content, e.target)) { this.props.onBlur(); diff --git a/lib/components/__tests__/Tray-test.js b/lib/components/__tests__/Tray-test.js index 6528228..c3b0dd4 100644 --- a/lib/components/__tests__/Tray-test.js +++ b/lib/components/__tests__/Tray-test.js @@ -116,4 +116,23 @@ describe('react-tray', function() { equal(document.activeElement, lastItem); }); }); + + describe('focusAfterOpen prop', function() { + beforeEach(function(done) { + const props = {isOpen: true, onBlur: function() {}, closeTimeoutMS: 0, maintainFocus: true, focusAfterOpen: '#two'}; + const children = ( +
+ One + Two + Three +
+ ); + renderTray(props, children, () => done()); + }); + + it('sends focus to the DOM node found via the selector passed in the prop', function() { + const secondItem = document.querySelector('#two'); + equal(document.activeElement, secondItem); + }); + }); });