Fix dropdown keyboard selection accessibility

This commit is contained in:
Michael Telatynski 2021-08-06 14:48:46 +01:00
parent 3fd2c00516
commit 6fddfe0d59

View file

@ -18,7 +18,7 @@ limitations under the License.
import React, { ChangeEvent, createRef, CSSProperties, ReactElement, ReactNode, Ref } from 'react'; import React, { ChangeEvent, createRef, CSSProperties, ReactElement, ReactNode, Ref } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import AccessibleButton from './AccessibleButton'; import AccessibleButton, { ButtonEvent } from './AccessibleButton';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { Key } from "../../../Keyboard"; import { Key } from "../../../Keyboard";
import { replaceableComponent } from "../../../utils/replaceableComponent"; import { replaceableComponent } from "../../../utils/replaceableComponent";
@ -178,7 +178,7 @@ export default class Dropdown extends React.Component<IProps, IState> {
this.ignoreEvent = ev; this.ignoreEvent = ev;
}; };
private onInputClick = (ev: React.MouseEvent) => { private onAccessibleButtonClick = (ev: ButtonEvent) => {
if (this.props.disabled) return; if (this.props.disabled) return;
if (!this.state.expanded) { if (!this.state.expanded) {
@ -186,6 +186,10 @@ export default class Dropdown extends React.Component<IProps, IState> {
expanded: true, expanded: true,
}); });
ev.preventDefault(); ev.preventDefault();
} else if ((ev as React.KeyboardEvent).key === Key.ENTER) {
// the accessible button consumes enter onKeyDown for firing onClick, so handle it here
this.props.onOptionChange(this.state.highlightedOption);
this.close();
} }
}; };
@ -328,6 +332,7 @@ export default class Dropdown extends React.Component<IProps, IState> {
aria-owns={`${this.props.id}_listbox`} aria-owns={`${this.props.id}_listbox`}
aria-disabled={this.props.disabled} aria-disabled={this.props.disabled}
aria-label={this.props.label} aria-label={this.props.label}
onKeyDown={this.onKeyDown}
/> />
); );
} }
@ -357,16 +362,17 @@ export default class Dropdown extends React.Component<IProps, IState> {
// Note the menu sits inside the AccessibleButton div so it's anchored // Note the menu sits inside the AccessibleButton div so it's anchored
// to the input, but overflows below it. The root contains both. // to the input, but overflows below it. The root contains both.
return <div className={classnames(dropdownClasses)} ref={this.collectRoot} onKeyDown={this.onKeyDown}> return <div className={classnames(dropdownClasses)} ref={this.collectRoot}>
<AccessibleButton <AccessibleButton
className="mx_Dropdown_input mx_no_textinput" className="mx_Dropdown_input mx_no_textinput"
onClick={this.onInputClick} onClick={this.onAccessibleButtonClick}
aria-haspopup="listbox" aria-haspopup="listbox"
aria-expanded={this.state.expanded} aria-expanded={this.state.expanded}
disabled={this.props.disabled} disabled={this.props.disabled}
inputRef={this.buttonRef} inputRef={this.buttonRef}
aria-label={this.props.label} aria-label={this.props.label}
aria-describedby={`${this.props.id}_value`} aria-describedby={`${this.props.id}_value`}
onKeyDown={this.onKeyDown}
> >
{ currentValue } { currentValue }
<span className="mx_Dropdown_arrow" /> <span className="mx_Dropdown_arrow" />