Skip to content

Commit

Permalink
[fixed] focus returns to the toggle by default onClose
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Aug 29, 2015
1 parent 6c554d5 commit da1d0bc
Showing 1 changed file with 34 additions and 18 deletions.
52 changes: 34 additions & 18 deletions src/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import ButtonGroup from './ButtonGroup';
import DropdownToggle from './DropdownToggle';
import DropdownMenu from './DropdownMenu';
import CustomPropTypes from './utils/CustomPropTypes';
import ValidComponentChildren from './utils/ValidComponentChildren';
import createChainedFunction from './utils/createChainedFunction';
import find from 'lodash/collection/find';
import omit from 'lodash/object/omit';

import activeElement from 'dom-helpers/activeElement';
import contains from 'dom-helpers/query/contains';

const TOGGLE_REF = 'toggle-btn';

export const TOGGLE_ROLE = DropdownToggle.defaultProps.bsRole;
Expand Down Expand Up @@ -52,11 +56,30 @@ class Dropdown extends React.Component {
}
}

componentDidUpdate(prevProps, prevState) {
componentWillUpdate(nextProps) {
if (!nextProps.open && this.props.open) {
this._focusInDropdown = contains(
React.findDOMNode(this.refs.menu),
activeElement(document)
);
}
}

componentDidUpdate(prevProps) {
let menu = this.refs.menu;

if (this.props.open && !prevProps.open && menu.focusNext) {
menu.focusNext();
}

if (!this.props.open && prevProps.open) {
// if focus hasn't already moved from the menu lets return it
// to the toggle
if (this._focusInDropdown) {
this._focusInDropdown = false;
this.focus();
}
}
}

render() {
Expand All @@ -74,6 +97,7 @@ class Dropdown extends React.Component {
return (
<Component
{...props}
tabIndex='-1'
className={classNames(this.props.className, rootClasses)}
>
{ children }
Expand All @@ -84,7 +108,7 @@ class Dropdown extends React.Component {
toggleOpen() {
let open = !this.props.open;

if (this.props.onToggle){
if (this.props.onToggle) {
this.props.onToggle(open);
}
}
Expand Down Expand Up @@ -115,9 +139,7 @@ class Dropdown extends React.Component {
break;
case keycode.codes.esc:
case keycode.codes.tab:
if (this.props.open) {
this.handleClose(event);
}
this.handleClose(event);
break;
default:
}
Expand All @@ -128,19 +150,13 @@ class Dropdown extends React.Component {
return;
}

// we need to let the current event finish before closing the menu.
// otherwise the menu may close, shifting focus to document.body, before focus has moved
// to the next focusable input
if (event && event.keyCode === keycode.codes.tab){
setTimeout(this.toggleOpen);
} else {
this.toggleOpen();
}
this.toggleOpen();
}

if (event && event.type === 'keydown' && event.keyCode === keycode.codes.esc) {
let toggle = React.findDOMNode(this.refs[TOGGLE_REF]);
event.preventDefault();
event.stopPropagation();
focus(){
let toggle = React.findDOMNode(this.refs[TOGGLE_REF]);

if (toggle && toggle.focus) {
toggle.focus();
}
}
Expand All @@ -149,7 +165,7 @@ class Dropdown extends React.Component {
let open = !!this.props.open;
let seen = {};

return React.Children.map(this.props.children, child => {
return ValidComponentChildren.map(this.props.children, child => {
let extractor = find(this.childExtractors, x => x.matches(child));

if (extractor) {
Expand Down

0 comments on commit da1d0bc

Please sign in to comment.