Improve a11y:
+ Close context menu on escape + Use AccessibleButtons for more things (Context Menus and TabbedView) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
8ec0ffea3a
commit
c37e27f03d
6 changed files with 86 additions and 94 deletions
|
@ -21,6 +21,7 @@ import ReactDOM from 'react-dom';
|
|||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import {focusCapturedRef} from "../../utils/Accessibility";
|
||||
import {KeyCode} from "../../Keyboard";
|
||||
|
||||
// Shamelessly ripped off Modal.js. There's probably a better way
|
||||
// of doing reusable widgets like dialog boxes & menus where we go and
|
||||
|
@ -67,7 +68,7 @@ export default class ContextualMenu extends React.Component {
|
|||
// on resize callback
|
||||
windowResize: PropTypes.func,
|
||||
// method to close menu
|
||||
closeMenu: PropTypes.func,
|
||||
closeMenu: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
|
@ -114,6 +115,14 @@ export default class ContextualMenu extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
_onKeyDown = (ev) => {
|
||||
if (ev.keyCode === KeyCode.ESCAPE) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
this.props.closeMenu();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const position = {};
|
||||
let chevronFace = null;
|
||||
|
@ -210,7 +219,7 @@ export default class ContextualMenu extends React.Component {
|
|||
|
||||
// FIXME: If a menu uses getDefaultProps it clobbers the onFinished
|
||||
// property set here so you can't close the menu from a button click!
|
||||
return <div className={className} style={{...position, ...wrapperStyle}}>
|
||||
return <div className={className} style={{...position, ...wrapperStyle}} onKeyDown={this._onKeyDown}>
|
||||
<div className={menuClasses} style={menuStyle} ref={this.collectContextMenuRect} tabIndex={0}>
|
||||
{ chevron }
|
||||
<ElementClass {...props} onFinished={props.closeMenu} onResize={props.windowResize} />
|
||||
|
|
|
@ -17,9 +17,9 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import {_t} from '../../languageHandler';
|
||||
import {KeyCode} from "../../Keyboard";
|
||||
import {_t} from '../../languageHandler';``
|
||||
import PropTypes from "prop-types";
|
||||
import sdk from "../../index";
|
||||
|
||||
/**
|
||||
* Represents a tab for the TabbedView.
|
||||
|
@ -72,6 +72,8 @@ export class TabbedView extends React.Component {
|
|||
}
|
||||
|
||||
_renderTabLabel(tab) {
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
|
||||
let classes = "mx_TabbedView_tabLabel ";
|
||||
|
||||
const idx = this.props.tabs.indexOf(tab);
|
||||
|
@ -83,30 +85,15 @@ export class TabbedView extends React.Component {
|
|||
}
|
||||
|
||||
const onClickHandler = () => this._setActiveTab(tab);
|
||||
const onKeyDownHandler = (e) => {
|
||||
if (e.keyCode === KeyCode.ENTER || e.keyCode === KeyCode.SPACE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this._setActiveTab(tab);
|
||||
}
|
||||
};
|
||||
|
||||
const label = _t(tab.label);
|
||||
return (
|
||||
<span
|
||||
className={classes}
|
||||
key={"tab_label_" + tab.label}
|
||||
onClick={onClickHandler}
|
||||
onKeyDown={onKeyDownHandler}
|
||||
role="button"
|
||||
aria-label={label}
|
||||
tabIndex={0}
|
||||
>
|
||||
<AccessibleButton className={classes} key={"tab_label_" + tab.label} onClick={onClickHandler}>
|
||||
{tabIcon}
|
||||
<span className="mx_TabbedView_tabLabel_text">
|
||||
{ label }
|
||||
</span>
|
||||
</span>
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,10 +109,11 @@ export default class TopLeftMenuButton extends React.Component {
|
|||
return (
|
||||
<AccessibleButton
|
||||
className="mx_TopLeftMenuButton"
|
||||
role="button"
|
||||
onClick={this.onToggleMenu}
|
||||
inputRef={(r) => this._buttonRef = r}
|
||||
aria-label={_t("Your profile")}
|
||||
aria-haspopup={true}
|
||||
aria-expanded={this.state.menuDisplayed}
|
||||
>
|
||||
<BaseAvatar
|
||||
idName={MatrixClientPeg.get().getUserId()}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue