fix focus and tab order bugs

This commit is contained in:
KDSBrowne 2017-05-06 16:04:59 -07:00
parent 569ba42042
commit 8bb1da0ed5
7 changed files with 130 additions and 27 deletions

View File

@ -18,7 +18,94 @@ const propTypes = {
class EmojiMenu extends Component {
constructor(props) {
super(props);
// this.rovingIndex = this.rovingIndex.bind(this);
}
/*
rovingIndex(...Args) {
const {users, openChats} = this.props;
let active = document.activeElement;
let list;
let items;
let count;
function focusList() {
active.tabIndex = -1;
this.counter = 0;
list.tabIndex = 0;
list.focus();
}
if (Args[1] === 'users'){
list = findDOMNode(this.refs.usersList);
items = findDOMNode(this.refs.userItems);
count = users.length;
}else if(Args[1] === 'messages'){
list = findDOMNode(this.refs.msgList);
items = findDOMNode(this.refs.msgItems);
count = openChats.length;
}
if(this.counter === -1 || this.counter > count){
active.tabIndex = -1;
list.tabIndex = 0;
this.counter = 0;
list.focus();
}
if (Args[0].keyCode === KEY_CODES.ENTER
|| Args[0].keyCode === KEY_CODES.ARROW_RIGHT
|| Args[0].keyCode === KEY_CODES.ARROW_LEFT) {
active.firstChild.click();
}
if (Args[0].keyCode === KEY_CODES.ESCAPE) {
active.tabIndex = -1;
focusList();
}
if (Args[0].keyCode === KEY_CODES.ARROW_DOWN) {
if (this.counter < count) {
active.tabIndex = -1;
items.childNodes[this.counter].tabIndex = 0;
let newFocus = items.childNodes[this.counter];
this.counter++;
newFocus.focus();
}else if(this.counter === count){
active.tabIndex = -1;
this.counter = -1;
list.tabIndex = 0;
list.focus();
}else if(this.counter === 0) {
active.tabIndex = -1;
this.counter = 1;
items.childNodes[this.counter].tabIndex = 0;
let newFocus = items.childNodes[this.counter];
newFocus.focus();
}
}
if (Args[0].keyCode === KEY_CODES.ARROW_UP) {
if (this.counter < count && this.counter !== 0) {
active.tabIndex = -1;
this.counter--;
items.childNodes[this.counter].tabIndex = 0;
let newFocus = items.childNodes[this.counter];
newFocus.focus();
}else if(this.counter === 0){
active.tabIndex = -1;
this.counter = count;
list.tabIndex = 0;
list.focus();
}else if (this.counter === count){
active.tabIndex = -1;
this.counter = count - 1;
items.childNodes[this.counter].tabIndex = 0;
let newFocus = items.childNodes[this.counter];
newFocus.focus();
}
}
} */
render() {
const {
@ -29,7 +116,7 @@ class EmojiMenu extends Component {
return (
<Dropdown ref="dropdown" autoFocus={true}>
<DropdownTrigger>
<DropdownTrigger placeInTabOrder={true}>
<Button
role="button"
label={intl.formatMessage(intlMessages.statusTriggerLabel)}
@ -51,60 +138,69 @@ class EmojiMenu extends Component {
</Button>
</DropdownTrigger>
<DropdownContent placement="top left">
<DropdownList>
<DropdownList ref={'dropdown'}>
<DropdownListItem
icon="hand"
label={intl.formatMessage(intlMessages.raiseLabel)}
description={intl.formatMessage(intlMessages.raiseDesc)}
onClick={() => actions.setEmojiHandler('raiseHand')}
tabIndex={-1}
/>
<DropdownListItem
icon="happy"
label={intl.formatMessage(intlMessages.happyLabel)}
description={intl.formatMessage(intlMessages.happyDesc)}
onClick={() => actions.setEmojiHandler('happy')}
tabIndex={-1}
/>
<DropdownListItem
icon="undecided"
label={intl.formatMessage(intlMessages.undecidedLabel)}
description={intl.formatMessage(intlMessages.undecidedDesc)}
onClick={() => actions.setEmojiHandler('neutral')}
tabIndex={-1}
/>
<DropdownListItem
icon="sad"
label={intl.formatMessage(intlMessages.sadLabel)}
description={intl.formatMessage(intlMessages.sadDesc)}
onClick={() => actions.setEmojiHandler('sad')}
tabIndex={-1}
/>
<DropdownListItem
icon="confused"
label={intl.formatMessage(intlMessages.confusedLabel)}
description={intl.formatMessage(intlMessages.confusedDesc)}
onClick={() => actions.setEmojiHandler('confused')}
tabIndex={-1}
/>
<DropdownListItem
icon="time"
label={intl.formatMessage(intlMessages.awayLabel)}
description={intl.formatMessage(intlMessages.awayDesc)}
onClick={() => actions.setEmojiHandler('away')}
tabIndex={-1}
/>
<DropdownListItem
icon="thumbs_up"
label={intl.formatMessage(intlMessages.thumbsupLabel)}
description={intl.formatMessage(intlMessages.thumbsupDesc)}
onClick={() => actions.setEmojiHandler('thumbsUp')}
tabIndex={-1}
/>
<DropdownListItem
icon="thumbs_down"
label={intl.formatMessage(intlMessages.thumbsdownLabel)}
description={intl.formatMessage(intlMessages.thumbsdownDesc)}
onClick={() => actions.setEmojiHandler('thumbsDown')}
tabIndex={-1}
/>
<DropdownListItem
icon="applause"
label={intl.formatMessage(intlMessages.applauseLabel)}
description={intl.formatMessage(intlMessages.applauseDesc)}
onClick={() => actions.setEmojiHandler('applause')}
tabIndex={-1}
/>
<DropdownListSeparator />
<DropdownListItem
@ -112,6 +208,7 @@ class EmojiMenu extends Component {
label={intl.formatMessage(intlMessages.clearLabel)}
description={intl.formatMessage(intlMessages.clearDesc)}
onClick={() => actions.setEmojiHandler('none')}
tabIndex={-1}
/>
</DropdownList>
</DropdownContent>

View File

@ -60,30 +60,30 @@ export default class DropdownList extends Component {
return event.currentTarget.click();
}
//let nextActiveItemIndex = null;
let nextActiveItemIndex = null;
//if (KEY_CODES.ARROW_UP === event.which) {
// nextActiveItemIndex = activeItemIndex - 1;
//}
if (KEY_CODES.ARROW_UP === event.which) {
nextActiveItemIndex = activeItemIndex - 1;
}
//if (KEY_CODES.ARROW_DOWN === event.which) {
// nextActiveItemIndex = activeItemIndex + 1;
//}
if (KEY_CODES.ARROW_DOWN === event.which) {
nextActiveItemIndex = activeItemIndex + 1;
}
//if (nextActiveItemIndex > (this.childrenRefs.length - 1)) {
// nextActiveItemIndex = 0;
//}
if (nextActiveItemIndex > (this.childrenRefs.length - 1)) {
nextActiveItemIndex = 0;
}
//if (nextActiveItemIndex < 0) {
// nextActiveItemIndex = this.childrenRefs.length - 1;
//}
if (nextActiveItemIndex < 0) {
nextActiveItemIndex = this.childrenRefs.length - 1;
}
//if ([KEY_CODES.TAB, KEY_CODES.ESCAPE].includes(event.which)) {
// nextActiveItemIndex = 0;
// dropdownHide();
//}
if ([KEY_CODES.ESCAPE].includes(event.which)) {
nextActiveItemIndex = 0;
dropdownHide();
}
//this.setState({ activeItemIndex: nextActiveItemIndex });
this.setState({ activeItemIndex: nextActiveItemIndex });
if (typeof callback === 'function') {
callback(event);

View File

@ -29,14 +29,16 @@ export default class DropdownListItem extends Component {
render() {
const { label, description, children, injectRef, tabIndex, onClick, onKeyDown,
className, style, separator, intl, } = this.props;
className, style, separator, intl, placeInTabOrder } = this.props;
let index = (placeInTabOrder) ? 0 : -1;
return (
<li
ref={injectRef}
onClick={onClick}
onKeyDown={onKeyDown}
tabIndex={tabIndex}
tabIndex={index}
aria-labelledby={this.labelID}
aria-describedby={this.descID}
className={cx(styles.item, className)}

View File

@ -41,14 +41,16 @@ export default class DropdownTrigger extends Component {
}
render() {
const { children, style, className, } = this.props;
const { children, style, className, placeInTabOrder} = this.props;
const TriggerComponent = React.Children.only(children);
let index = (placeInTabOrder) ? '0' : '-1';
const TriggerComponentBounded = React.cloneElement(children, {
onClick: this.handleClick,
onKeyDown: this.handleKeyDown,
'aria-haspopup': true,
tabIndex: '-1',
tabIndex: index,
style: style,
className: cx(children.props.className, className),
});

View File

@ -84,7 +84,7 @@ class SettingsDropdown extends Component {
return (
<Dropdown ref="dropdown" autoFocus={true}>
<DropdownTrigger>
<DropdownTrigger placeInTabOrder={true}>
<Button
label={intl.formatMessage(intlMessages.optionsLabel)}
icon="more"

View File

@ -61,7 +61,8 @@ class UserList extends Component {
count = openChats.length;
}
if(this.counter === -1){
if(this.counter === -1 || this.counter > count){
active.tabIndex = -1;
list.tabIndex = 0;
this.counter = 0;
list.focus();

View File

@ -444,6 +444,7 @@ class UserListItem extends Component {
defaultMessage={action.label}
onClick={action.handler.bind(this, ...parameters)}
ref={"test"}
placeInTabOrder={true}
/>
);