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:
Michael Telatynski 2019-09-26 14:52:20 +01:00
parent 8ec0ffea3a
commit c37e27f03d
6 changed files with 86 additions and 94 deletions

View file

@ -21,6 +21,7 @@ import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import {focusCapturedRef} from "../../utils/Accessibility"; import {focusCapturedRef} from "../../utils/Accessibility";
import {KeyCode} from "../../Keyboard";
// Shamelessly ripped off Modal.js. There's probably a better way // Shamelessly ripped off Modal.js. There's probably a better way
// of doing reusable widgets like dialog boxes & menus where we go and // 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 // on resize callback
windowResize: PropTypes.func, windowResize: PropTypes.func,
// method to close menu // method to close menu
closeMenu: PropTypes.func, closeMenu: PropTypes.func.isRequired,
}; };
constructor() { 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() { render() {
const position = {}; const position = {};
let chevronFace = null; let chevronFace = null;
@ -210,7 +219,7 @@ export default class ContextualMenu extends React.Component {
// FIXME: If a menu uses getDefaultProps it clobbers the onFinished // FIXME: If a menu uses getDefaultProps it clobbers the onFinished
// property set here so you can't close the menu from a button click! // 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}> <div className={menuClasses} style={menuStyle} ref={this.collectContextMenuRect} tabIndex={0}>
{ chevron } { chevron }
<ElementClass {...props} onFinished={props.closeMenu} onResize={props.windowResize} /> <ElementClass {...props} onFinished={props.closeMenu} onResize={props.windowResize} />

View file

@ -17,9 +17,9 @@ limitations under the License.
*/ */
import * as React from "react"; import * as React from "react";
import {_t} from '../../languageHandler'; import {_t} from '../../languageHandler';``
import {KeyCode} from "../../Keyboard";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import sdk from "../../index";
/** /**
* Represents a tab for the TabbedView. * Represents a tab for the TabbedView.
@ -72,6 +72,8 @@ export class TabbedView extends React.Component {
} }
_renderTabLabel(tab) { _renderTabLabel(tab) {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let classes = "mx_TabbedView_tabLabel "; let classes = "mx_TabbedView_tabLabel ";
const idx = this.props.tabs.indexOf(tab); const idx = this.props.tabs.indexOf(tab);
@ -83,30 +85,15 @@ export class TabbedView extends React.Component {
} }
const onClickHandler = () => this._setActiveTab(tab); 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); const label = _t(tab.label);
return ( return (
<span <AccessibleButton className={classes} key={"tab_label_" + tab.label} onClick={onClickHandler}>
className={classes}
key={"tab_label_" + tab.label}
onClick={onClickHandler}
onKeyDown={onKeyDownHandler}
role="button"
aria-label={label}
tabIndex={0}
>
{tabIcon} {tabIcon}
<span className="mx_TabbedView_tabLabel_text"> <span className="mx_TabbedView_tabLabel_text">
{ label } { label }
</span> </span>
</span> </AccessibleButton>
); );
} }

View file

@ -109,10 +109,11 @@ export default class TopLeftMenuButton extends React.Component {
return ( return (
<AccessibleButton <AccessibleButton
className="mx_TopLeftMenuButton" className="mx_TopLeftMenuButton"
role="button"
onClick={this.onToggleMenu} onClick={this.onToggleMenu}
inputRef={(r) => this._buttonRef = r} inputRef={(r) => this._buttonRef = r}
aria-label={_t("Your profile")} aria-label={_t("Your profile")}
aria-haspopup={true}
aria-expanded={this.state.menuDisplayed}
> >
<BaseAvatar <BaseAvatar
idName={MatrixClientPeg.get().getUserId()} idName={MatrixClientPeg.get().getUserId()}

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2018 Vector Creations Ltd Copyright 2018 Vector Creations Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -77,11 +78,12 @@ export default class GroupInviteTileContextMenu extends React.Component {
} }
render() { render() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return <div> return <div>
<div className="mx_RoomTileContextMenu_leave" onClick={this._onClickReject} > <AccessibleButton className="mx_RoomTileContextMenu_leave" onClick={this._onClickReject} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" />
{ _t('Reject') } { _t('Reject') }
</div> </AccessibleButton>
</div>; </div>;
} }
} }

View file

@ -31,28 +31,11 @@ import Resend from '../../../Resend';
import SettingsStore from '../../../settings/SettingsStore'; import SettingsStore from '../../../settings/SettingsStore';
import { isUrlPermitted } from '../../../HtmlUtils'; import { isUrlPermitted } from '../../../HtmlUtils';
import { isContentActionable } from '../../../utils/EventUtils'; import { isContentActionable } from '../../../utils/EventUtils';
import {KeyCode} from "../../../Keyboard";
function canCancel(eventStatus) { function canCancel(eventStatus) {
return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT; return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
} }
const DropdownButton = ({children, onClick}) => {
const onKeyDown = (e) => {
if (e.keyCode === KeyCode.ENTER || e.keyCode === KeyCode.SPACE) {
e.stopPropagation();
e.preventDefault();
onClick();
}
};
return (
<div className="mx_MessageContextMenu_field" onClick={onClick} onKeyDown={onKeyDown} role="button" tabIndex={0}>
{ children }
</div>
);
};
module.exports = createReactClass({ module.exports = createReactClass({
displayName: 'MessageContextMenu', displayName: 'MessageContextMenu',
@ -306,6 +289,8 @@ module.exports = createReactClass({
}, },
render: function() { render: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const me = cli.getUserId(); const me = cli.getUserId();
const mxEvent = this.props.mxEvent; const mxEvent = this.props.mxEvent;
@ -337,89 +322,89 @@ module.exports = createReactClass({
if (!mxEvent.isRedacted()) { if (!mxEvent.isRedacted()) {
if (eventStatus === EventStatus.NOT_SENT) { if (eventStatus === EventStatus.NOT_SENT) {
resendButton = ( resendButton = (
<DropdownButton onClick={this.onResendClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendClick}>
{ _t('Resend') } { _t('Resend') }
</DropdownButton> </AccessibleButton>
); );
} }
if (editStatus === EventStatus.NOT_SENT) { if (editStatus === EventStatus.NOT_SENT) {
resendEditButton = ( resendEditButton = (
<DropdownButton onClick={this.onResendEditClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendEditClick}>
{ _t('Resend edit') } { _t('Resend edit') }
</DropdownButton> </AccessibleButton>
); );
} }
if (unsentReactionsCount !== 0) { if (unsentReactionsCount !== 0) {
resendReactionsButton = ( resendReactionsButton = (
<DropdownButton onClick={this.onResendReactionsClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendReactionsClick}>
{ _t('Resend %(unsentCount)s reaction(s)', {unsentCount: unsentReactionsCount}) } { _t('Resend %(unsentCount)s reaction(s)', {unsentCount: unsentReactionsCount}) }
</DropdownButton> </AccessibleButton>
); );
} }
} }
if (redactStatus === EventStatus.NOT_SENT) { if (redactStatus === EventStatus.NOT_SENT) {
resendRedactionButton = ( resendRedactionButton = (
<DropdownButton onClick={this.onResendRedactionClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onResendRedactionClick}>
{ _t('Resend removal') } { _t('Resend removal') }
</DropdownButton> </AccessibleButton>
); );
} }
if (isSent && this.state.canRedact) { if (isSent && this.state.canRedact) {
redactButton = ( redactButton = (
<DropdownButton onClick={this.onRedactClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onRedactClick}>
{ _t('Remove') } { _t('Remove') }
</DropdownButton> </AccessibleButton>
); );
} }
if (allowCancel) { if (allowCancel) {
cancelButton = ( cancelButton = (
<DropdownButton onClick={this.onCancelSendClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onCancelSendClick}>
{ _t('Cancel Sending') } { _t('Cancel Sending') }
</DropdownButton> </AccessibleButton>
); );
} }
if (isContentActionable(mxEvent)) { if (isContentActionable(mxEvent)) {
forwardButton = ( forwardButton = (
<DropdownButton onClick={this.onForwardClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onForwardClick}>
{ _t('Forward Message') } { _t('Forward Message') }
</DropdownButton> </AccessibleButton>
); );
if (this.state.canPin) { if (this.state.canPin) {
pinButton = ( pinButton = (
<DropdownButton onClick={this.onPinClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onPinClick}>
{ this._isPinned() ? _t('Unpin Message') : _t('Pin Message') } { this._isPinned() ? _t('Unpin Message') : _t('Pin Message') }
</DropdownButton> </AccessibleButton>
); );
} }
} }
const viewSourceButton = ( const viewSourceButton = (
<DropdownButton onClick={this.onViewSourceClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onViewSourceClick}>
{ _t('View Source') } { _t('View Source') }
</DropdownButton> </AccessibleButton>
); );
if (mxEvent.getType() !== mxEvent.getWireType()) { if (mxEvent.getType() !== mxEvent.getWireType()) {
viewClearSourceButton = ( viewClearSourceButton = (
<DropdownButton onClick={this.onViewClearSourceClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onViewClearSourceClick}>
{ _t('View Decrypted Source') } { _t('View Decrypted Source') }
</DropdownButton> </AccessibleButton>
); );
} }
if (this.props.eventTileOps) { if (this.props.eventTileOps) {
if (this.props.eventTileOps.isWidgetHidden()) { if (this.props.eventTileOps.isWidgetHidden()) {
unhidePreviewButton = ( unhidePreviewButton = (
<DropdownButton onClick={this.onUnhidePreviewClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onUnhidePreviewClick}>
{ _t('Unhide Preview') } { _t('Unhide Preview') }
</DropdownButton> </AccessibleButton>
); );
} }
} }
@ -430,19 +415,19 @@ module.exports = createReactClass({
} }
// XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID) // XXX: if we use room ID, we should also include a server where the event can be found (other than in the domain of the event ID)
const permalinkButton = ( const permalinkButton = (
<DropdownButton> <AccessibleButton className="mx_MessageContextMenu_field">
<a href={permalink} target="_blank" rel="noopener" onClick={this.onPermalinkClick} tabIndex={-1}> <a href={permalink} target="_blank" rel="noopener" onClick={this.onPermalinkClick} tabIndex={-1}>
{ mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message'
? _t('Share Permalink') : _t('Share Message') } ? _t('Share Permalink') : _t('Share Message') }
</a> </a>
</DropdownButton> </AccessibleButton>
); );
if (this.props.eventTileOps && this.props.eventTileOps.getInnerText) { if (this.props.eventTileOps && this.props.eventTileOps.getInnerText) {
quoteButton = ( quoteButton = (
<DropdownButton onClick={this.onQuoteClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onQuoteClick}>
{ _t('Quote') } { _t('Quote') }
</DropdownButton> </AccessibleButton>
); );
} }
@ -452,7 +437,7 @@ module.exports = createReactClass({
isUrlPermitted(mxEvent.event.content.external_url) isUrlPermitted(mxEvent.event.content.external_url)
) { ) {
externalURLButton = ( externalURLButton = (
<DropdownButton> <AccessibleButton className="mx_MessageContextMenu_field">
<a <a
href={mxEvent.event.content.external_url} href={mxEvent.event.content.external_url}
target="_blank" target="_blank"
@ -462,33 +447,33 @@ module.exports = createReactClass({
> >
{ _t('Source URL') } { _t('Source URL') }
</a> </a>
</DropdownButton> </AccessibleButton>
); );
} }
if (this.props.collapseReplyThread) { if (this.props.collapseReplyThread) {
collapseReplyThread = ( collapseReplyThread = (
<DropdownButton onClick={this.onCollapseReplyThreadClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onCollapseReplyThreadClick}>
{ _t('Collapse Reply Thread') } { _t('Collapse Reply Thread') }
</DropdownButton> </AccessibleButton>
); );
} }
let e2eInfo; let e2eInfo;
if (this.props.e2eInfoCallback) { if (this.props.e2eInfoCallback) {
e2eInfo = ( e2eInfo = (
<DropdownButton onClick={this.e2eInfoClicked}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.e2eInfoClicked}>
{ _t('End-to-end encryption information') } { _t('End-to-end encryption information') }
</DropdownButton> </AccessibleButton>
); );
} }
let reportEventButton; let reportEventButton;
if (mxEvent.getSender() !== me) { if (mxEvent.getSender() !== me) {
reportEventButton = ( reportEventButton = (
<DropdownButton onClick={this.onReportEventClick}> <AccessibleButton className="mx_MessageContextMenu_field" onClick={this.onReportEventClick}>
{ _t('Report Content') } { _t('Report Content') }
</DropdownButton> </AccessibleButton>
); );
} }

View file

@ -2,6 +2,7 @@
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd Copyright 2017 Vector Creations Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -227,6 +228,8 @@ module.exports = createReactClass({
}, },
_renderNotifMenu: function() { _renderNotifMenu: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const alertMeClasses = classNames({ const alertMeClasses = classNames({
'mx_RoomTileContextMenu_notif_field': true, 'mx_RoomTileContextMenu_notif_field': true,
'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD, 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD,
@ -249,29 +252,29 @@ module.exports = createReactClass({
return ( return (
<div className="mx_RoomTileContextMenu"> <div className="mx_RoomTileContextMenu">
<div className="mx_RoomTileContextMenu_notif_picker" > <div className="mx_RoomTileContextMenu_notif_picker">
<img src={require("../../../../res/img/notif-slider.svg")} width="20" height="107" /> <img src={require("../../../../res/img/notif-slider.svg")} width="20" height="107" />
</div> </div>
<div className={alertMeClasses} onClick={this._onClickAlertMe} > <AccessibleButton className={alertMeClasses} onClick={this._onClickAlertMe}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" /> <img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-off-copy.svg")} width="16" height="12" /> <img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-off-copy.svg")} width="16" height="12" />
{ _t('All messages (noisy)') } { _t('All messages (noisy)') }
</div> </AccessibleButton>
<div className={allNotifsClasses} onClick={this._onClickAllNotifs} > <AccessibleButton className={allNotifsClasses} onClick={this._onClickAllNotifs}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" /> <img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-off.svg")} width="16" height="12" /> <img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-off.svg")} width="16" height="12" />
{ _t('All messages') } { _t('All messages') }
</div> </AccessibleButton>
<div className={mentionsClasses} onClick={this._onClickMentions} > <AccessibleButton className={mentionsClasses} onClick={this._onClickMentions}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" /> <img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-mentions.svg")} width="16" height="12" /> <img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute-mentions.svg")} width="16" height="12" />
{ _t('Mentions only') } { _t('Mentions only') }
</div> </AccessibleButton>
<div className={muteNotifsClasses} onClick={this._onClickMute} > <AccessibleButton className={muteNotifsClasses} onClick={this._onClickMute}>
<img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" /> <img className="mx_RoomTileContextMenu_notif_activeIcon" src={require("../../../../res/img/notif-active.svg")} width="12" height="12" />
<img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute.svg")} width="16" height="12" /> <img className="mx_RoomTileContextMenu_notif_icon mx_filterFlipColor" src={require("../../../../res/img/icon-context-mute.svg")} width="16" height="12" />
{ _t('Mute') } { _t('Mute') }
</div> </AccessibleButton>
</div> </div>
); );
}, },
@ -287,12 +290,13 @@ module.exports = createReactClass({
}, },
_renderSettingsMenu: function() { _renderSettingsMenu: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
return ( return (
<div> <div>
<div className="mx_RoomTileContextMenu_tag_field" onClick={this._onClickSettings} > <AccessibleButton className="mx_RoomTileContextMenu_tag_field" onClick={this._onClickSettings} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icons-settings-room.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icons-settings-room.svg")} width="15" height="15" />
{ _t('Settings') } { _t('Settings') }
</div> </AccessibleButton>
</div> </div>
); );
}, },
@ -302,6 +306,8 @@ module.exports = createReactClass({
return null; return null;
} }
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
let leaveClickHandler = null; let leaveClickHandler = null;
let leaveText = null; let leaveText = null;
@ -323,15 +329,17 @@ module.exports = createReactClass({
return ( return (
<div> <div>
<div className="mx_RoomTileContextMenu_leave" onClick={leaveClickHandler} > <AccessibleButton className="mx_RoomTileContextMenu_leave" onClick={leaveClickHandler} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_delete.svg")} width="15" height="15" />
{ leaveText } { leaveText }
</div> </AccessibleButton>
</div> </div>
); );
}, },
_renderRoomTagMenu: function() { _renderRoomTagMenu: function() {
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const favouriteClasses = classNames({ const favouriteClasses = classNames({
'mx_RoomTileContextMenu_tag_field': true, 'mx_RoomTileContextMenu_tag_field': true,
'mx_RoomTileContextMenu_tag_fieldSet': this.state.isFavourite, 'mx_RoomTileContextMenu_tag_fieldSet': this.state.isFavourite,
@ -352,21 +360,21 @@ module.exports = createReactClass({
return ( return (
<div> <div>
<div className={favouriteClasses} onClick={this._onClickFavourite} > <AccessibleButton className={favouriteClasses} onClick={this._onClickFavourite} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_fave.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_fave.svg")} width="15" height="15" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_fave_on.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_fave_on.svg")} width="15" height="15" />
{ _t('Favourite') } { _t('Favourite') }
</div> </AccessibleButton>
<div className={lowPriorityClasses} onClick={this._onClickLowPriority} > <AccessibleButton className={lowPriorityClasses} onClick={this._onClickLowPriority} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_low.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_low.svg")} width="15" height="15" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_low_on.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_low_on.svg")} width="15" height="15" />
{ _t('Low Priority') } { _t('Low Priority') }
</div> </AccessibleButton>
<div className={dmClasses} onClick={this._onClickDM} > <AccessibleButton className={dmClasses} onClick={this._onClickDM} >
<img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_person.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon" src={require("../../../../res/img/icon_context_person.svg")} width="15" height="15" />
<img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_person_on.svg")} width="15" height="15" /> <img className="mx_RoomTileContextMenu_tag_icon_set" src={require("../../../../res/img/icon_context_person_on.svg")} width="15" height="15" />
{ _t('Direct Chat') } { _t('Direct Chat') }
</div> </AccessibleButton>
</div> </div>
); );
}, },