From 14e3cb87361de82e784f95ad154921225e39a849 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 26 Sep 2019 13:52:09 +0100 Subject: [PATCH 1/7] Allow keyboard control even without a screen reader Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/TabbedView.js | 10 ++++++++ src/components/views/elements/ToggleSwitch.js | 23 +++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/components/structures/TabbedView.js b/src/components/structures/TabbedView.js index 6ececbb329..cf603a75b3 100644 --- a/src/components/structures/TabbedView.js +++ b/src/components/structures/TabbedView.js @@ -1,6 +1,7 @@ /* Copyright 2017 Travis Ralston Copyright 2019 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,6 +18,7 @@ limitations under the License. import * as React from "react"; import {_t} from '../../languageHandler'; +import {KeyCode} from "../../Keyboard"; import PropTypes from "prop-types"; /** @@ -81,6 +83,13 @@ export class TabbedView extends React.Component { } const onClickHandler = () => this._setActiveTab(tab); + const onKeyDownHandler = (e) => { + e.stopPropagation(); + e.preventDefault(); + if (e.keyCode === KeyCode.ENTER || e.keyCode === KeyCode.SPACE) { + this._setActiveTab(tab); + } + }; const label = _t(tab.label); return ( @@ -88,6 +97,7 @@ export class TabbedView extends React.Component { className={classes} key={"tab_label_" + tab.label} onClick={onClickHandler} + onKeyDown={onKeyDownHandler} role="button" aria-label={label} tabIndex={0} diff --git a/src/components/views/elements/ToggleSwitch.js b/src/components/views/elements/ToggleSwitch.js index e8e870edd8..05986e4e99 100644 --- a/src/components/views/elements/ToggleSwitch.js +++ b/src/components/views/elements/ToggleSwitch.js @@ -17,6 +17,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import classNames from "classnames"; +import {KeyCode} from "../../../Keyboard"; export default class ToggleSwitch extends React.Component { static propTypes = { @@ -44,10 +45,7 @@ export default class ToggleSwitch extends React.Component { } } - _onClick = (e) => { - e.stopPropagation(); - e.preventDefault(); - + _toggle = () => { if (this.props.disabled) return; const newState = !this.state.checked; @@ -57,6 +55,22 @@ export default class ToggleSwitch extends React.Component { } }; + _onClick = (e) => { + e.stopPropagation(); + e.preventDefault(); + + this._toggle(); + }; + + _onKeyDown = (e) => { + e.stopPropagation(); + e.preventDefault(); + + if (e.keyCode === KeyCode.ENTER || e.keyCode === KeyCode.SPACE) { + this._toggle(); + } + }; + render() { // eslint-disable-next-line no-unused-vars const {checked, disabled, onChange, ...props} = this.props; @@ -71,6 +85,7 @@ export default class ToggleSwitch extends React.Component { {...props} className={classes} onClick={this._onClick} + onKeyDown={this._onKeyDown} role="checkbox" aria-checked={this.state.checked} aria-disabled={disabled} From 8ec0ffea3a5dac008e491617577f5905625ffeca Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 26 Sep 2019 14:24:10 +0100 Subject: [PATCH 2/7] Make the message context menu more accessible Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/TabbedView.js | 4 +- .../views/context_menus/MessageContextMenu.js | 102 +++++++++++------- .../views/messages/MessageActionBar.js | 4 +- 3 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/components/structures/TabbedView.js b/src/components/structures/TabbedView.js index cf603a75b3..0e76143f92 100644 --- a/src/components/structures/TabbedView.js +++ b/src/components/structures/TabbedView.js @@ -84,9 +84,9 @@ export class TabbedView extends React.Component { const onClickHandler = () => this._setActiveTab(tab); const onKeyDownHandler = (e) => { - e.stopPropagation(); - e.preventDefault(); if (e.keyCode === KeyCode.ENTER || e.keyCode === KeyCode.SPACE) { + e.stopPropagation(); + e.preventDefault(); this._setActiveTab(tab); } }; diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index 66005eb730..1d859da047 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -2,6 +2,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2018 New Vector Ltd 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"); you may not use this file except in compliance with the License. @@ -30,11 +31,28 @@ import Resend from '../../../Resend'; import SettingsStore from '../../../settings/SettingsStore'; import { isUrlPermitted } from '../../../HtmlUtils'; import { isContentActionable } from '../../../utils/EventUtils'; +import {KeyCode} from "../../../Keyboard"; function canCancel(eventStatus) { 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 ( +
+ { children } +
+ ); +}; + + module.exports = createReactClass({ displayName: 'MessageContextMenu', @@ -319,89 +337,89 @@ module.exports = createReactClass({ if (!mxEvent.isRedacted()) { if (eventStatus === EventStatus.NOT_SENT) { resendButton = ( -
+ { _t('Resend') } -
+ ); } if (editStatus === EventStatus.NOT_SENT) { resendEditButton = ( -
+ { _t('Resend edit') } -
+ ); } if (unsentReactionsCount !== 0) { resendReactionsButton = ( -
+ { _t('Resend %(unsentCount)s reaction(s)', {unsentCount: unsentReactionsCount}) } -
+ ); } } if (redactStatus === EventStatus.NOT_SENT) { resendRedactionButton = ( -
+ { _t('Resend removal') } -
+ ); } if (isSent && this.state.canRedact) { redactButton = ( -
+ { _t('Remove') } -
+ ); } if (allowCancel) { cancelButton = ( -
+ { _t('Cancel Sending') } -
+ ); } if (isContentActionable(mxEvent)) { forwardButton = ( -
+ { _t('Forward Message') } -
+ ); if (this.state.canPin) { pinButton = ( -
+ { this._isPinned() ? _t('Unpin Message') : _t('Pin Message') } -
+ ); } } const viewSourceButton = ( -
+ { _t('View Source') } -
+ ); if (mxEvent.getType() !== mxEvent.getWireType()) { viewClearSourceButton = ( -
+ { _t('View Decrypted Source') } -
+ ); } if (this.props.eventTileOps) { if (this.props.eventTileOps.isWidgetHidden()) { unhidePreviewButton = ( -
+ { _t('Unhide Preview') } -
+ ); } } @@ -412,20 +430,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) const permalinkButton = ( -
- + + { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' ? _t('Share Permalink') : _t('Share Message') } -
+ ); if (this.props.eventTileOps && this.props.eventTileOps.getInnerText) { quoteButton = ( -
+ { _t('Quote') } -
+ ); } @@ -435,34 +452,43 @@ module.exports = createReactClass({ isUrlPermitted(mxEvent.event.content.external_url) ) { externalURLButton = ( -
- { _t('Source URL') } -
+ + + { _t('Source URL') } + + ); } if (this.props.collapseReplyThread) { collapseReplyThread = ( -
+ { _t('Collapse Reply Thread') } -
+ ); } let e2eInfo; if (this.props.e2eInfoCallback) { - e2eInfo =
+ e2eInfo = ( + { _t('End-to-end encryption information') } -
; + + ); } let reportEventButton; if (mxEvent.getSender() !== me) { reportEventButton = ( -
+ { _t('Report Content') } -
+ ); } diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index 8db268076c..1797065f11 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -166,9 +166,11 @@ export default class MessageActionBar extends React.PureComponent { {reactButton} {replyButton} {editButton} - ; } From c37e27f03d2ed066c7bfea8c50ead8835657e57d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 26 Sep 2019 14:52:20 +0100 Subject: [PATCH 3/7] Improve a11y: + Close context menu on escape + Use AccessibleButtons for more things (Context Menus and TabbedView) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/ContextualMenu.js | 13 ++- src/components/structures/TabbedView.js | 25 ++---- .../structures/TopLeftMenuButton.js | 3 +- .../GroupInviteTileContextMenu.js | 6 +- .../views/context_menus/MessageContextMenu.js | 87 ++++++++----------- .../context_menus/RoomTileContextMenu.js | 46 ++++++---- 6 files changed, 86 insertions(+), 94 deletions(-) diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js index 0f4d0b38d4..04314e5a4e 100644 --- a/src/components/structures/ContextualMenu.js +++ b/src/components/structures/ContextualMenu.js @@ -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
+ return
{ chevron } diff --git a/src/components/structures/TabbedView.js b/src/components/structures/TabbedView.js index 0e76143f92..e6d61a2125 100644 --- a/src/components/structures/TabbedView.js +++ b/src/components/structures/TabbedView.js @@ -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 ( - + {tabIcon} { label } - + ); } diff --git a/src/components/structures/TopLeftMenuButton.js b/src/components/structures/TopLeftMenuButton.js index cf3dda077c..42b8623e56 100644 --- a/src/components/structures/TopLeftMenuButton.js +++ b/src/components/structures/TopLeftMenuButton.js @@ -109,10 +109,11 @@ export default class TopLeftMenuButton extends React.Component { return ( this._buttonRef = r} aria-label={_t("Your profile")} + aria-haspopup={true} + aria-expanded={this.state.menuDisplayed} > -
+ { _t('Reject') } -
+
; } } diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index 1d859da047..a832b2fbb2 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -31,28 +31,11 @@ import Resend from '../../../Resend'; import SettingsStore from '../../../settings/SettingsStore'; import { isUrlPermitted } from '../../../HtmlUtils'; import { isContentActionable } from '../../../utils/EventUtils'; -import {KeyCode} from "../../../Keyboard"; function canCancel(eventStatus) { 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 ( -
- { children } -
- ); -}; - - module.exports = createReactClass({ displayName: 'MessageContextMenu', @@ -306,6 +289,8 @@ module.exports = createReactClass({ }, render: function() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const cli = MatrixClientPeg.get(); const me = cli.getUserId(); const mxEvent = this.props.mxEvent; @@ -337,89 +322,89 @@ module.exports = createReactClass({ if (!mxEvent.isRedacted()) { if (eventStatus === EventStatus.NOT_SENT) { resendButton = ( - + { _t('Resend') } - + ); } if (editStatus === EventStatus.NOT_SENT) { resendEditButton = ( - + { _t('Resend edit') } - + ); } if (unsentReactionsCount !== 0) { resendReactionsButton = ( - + { _t('Resend %(unsentCount)s reaction(s)', {unsentCount: unsentReactionsCount}) } - + ); } } if (redactStatus === EventStatus.NOT_SENT) { resendRedactionButton = ( - + { _t('Resend removal') } - + ); } if (isSent && this.state.canRedact) { redactButton = ( - + { _t('Remove') } - + ); } if (allowCancel) { cancelButton = ( - + { _t('Cancel Sending') } - + ); } if (isContentActionable(mxEvent)) { forwardButton = ( - + { _t('Forward Message') } - + ); if (this.state.canPin) { pinButton = ( - + { this._isPinned() ? _t('Unpin Message') : _t('Pin Message') } - + ); } } const viewSourceButton = ( - + { _t('View Source') } - + ); if (mxEvent.getType() !== mxEvent.getWireType()) { viewClearSourceButton = ( - + { _t('View Decrypted Source') } - + ); } if (this.props.eventTileOps) { if (this.props.eventTileOps.isWidgetHidden()) { unhidePreviewButton = ( - + { _t('Unhide Preview') } - + ); } } @@ -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) const permalinkButton = ( - + { mxEvent.isRedacted() || mxEvent.getType() !== 'm.room.message' ? _t('Share Permalink') : _t('Share Message') } - + ); if (this.props.eventTileOps && this.props.eventTileOps.getInnerText) { quoteButton = ( - + { _t('Quote') } - + ); } @@ -452,7 +437,7 @@ module.exports = createReactClass({ isUrlPermitted(mxEvent.event.content.external_url) ) { externalURLButton = ( - + { _t('Source URL') } - + ); } if (this.props.collapseReplyThread) { collapseReplyThread = ( - + { _t('Collapse Reply Thread') } - + ); } let e2eInfo; if (this.props.e2eInfoCallback) { e2eInfo = ( - + { _t('End-to-end encryption information') } - + ); } let reportEventButton; if (mxEvent.getSender() !== me) { reportEventButton = ( - + { _t('Report Content') } - + ); } diff --git a/src/components/views/context_menus/RoomTileContextMenu.js b/src/components/views/context_menus/RoomTileContextMenu.js index eba8254c03..9bb573026f 100644 --- a/src/components/views/context_menus/RoomTileContextMenu.js +++ b/src/components/views/context_menus/RoomTileContextMenu.js @@ -2,6 +2,7 @@ Copyright 2015, 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd 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"); you may not use this file except in compliance with the License. @@ -227,6 +228,8 @@ module.exports = createReactClass({ }, _renderNotifMenu: function() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const alertMeClasses = classNames({ 'mx_RoomTileContextMenu_notif_field': true, 'mx_RoomTileContextMenu_notif_fieldSet': this.state.roomNotifState == RoomNotifs.ALL_MESSAGES_LOUD, @@ -249,29 +252,29 @@ module.exports = createReactClass({ return (
-
+
-
+ { _t('All messages (noisy)') } -
-
+ + { _t('All messages') } -
-
+ + { _t('Mentions only') } -
-
+ + { _t('Mute') } -
+
); }, @@ -287,12 +290,13 @@ module.exports = createReactClass({ }, _renderSettingsMenu: function() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return (
-
+ { _t('Settings') } -
+
); }, @@ -302,6 +306,8 @@ module.exports = createReactClass({ return null; } + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + let leaveClickHandler = null; let leaveText = null; @@ -323,15 +329,17 @@ module.exports = createReactClass({ return (
-
+ { leaveText } -
+
); }, _renderRoomTagMenu: function() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const favouriteClasses = classNames({ 'mx_RoomTileContextMenu_tag_field': true, 'mx_RoomTileContextMenu_tag_fieldSet': this.state.isFavourite, @@ -352,21 +360,21 @@ module.exports = createReactClass({ return (
-
+ { _t('Favourite') } -
-
+ + { _t('Low Priority') } -
-
+ + { _t('Direct Chat') } -
+
); }, From 3674b874156f5b6394eac1f11e57e9d760b0ac9e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 26 Sep 2019 14:58:40 +0100 Subject: [PATCH 4/7] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/TabbedView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/TabbedView.js b/src/components/structures/TabbedView.js index e6d61a2125..01c68fad62 100644 --- a/src/components/structures/TabbedView.js +++ b/src/components/structures/TabbedView.js @@ -17,7 +17,7 @@ limitations under the License. */ import * as React from "react"; -import {_t} from '../../languageHandler';`` +import {_t} from '../../languageHandler'; import PropTypes from "prop-types"; import sdk from "../../index"; From 8d1d3090f36963c0f3921968f09b20d680810d80 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 27 Sep 2019 09:00:54 +0100 Subject: [PATCH 5/7] Improve keyboard accessibility using :focus-visible CSS polyfill Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 1 + res/css/views/elements/_AccessibleButton.scss | 2 +- src/components/structures/MatrixChat.js | 4 ++- .../views/context_menus/TopLeftMenu.js | 35 ++++++++++++------- .../views/messages/MessageActionBar.js | 10 ++++-- yarn.lock | 5 +++ 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 958b782ac3..6c66ebed52 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "filesize": "3.5.6", "flux": "2.1.1", "focus-trap-react": "^3.0.5", + "focus-visible": "^5.0.2", "fuse.js": "^2.2.0", "gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566", "gfm.css": "^1.1.1", diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 0c081ec0d5..0cf1a78c4f 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -18,7 +18,7 @@ limitations under the License. cursor: pointer; } -.mx_AccessibleButton:focus { +.mx_AccessibleButton:focus:not(.focus-visible) { outline: 0; } diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index a185664038..dccc7be2f1 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -41,7 +41,9 @@ import * as Rooms from '../../Rooms'; import linkifyMatrix from "../../linkify-matrix"; import * as Lifecycle from '../../Lifecycle'; // LifecycleStore is not used but does listen to and dispatch actions -require('../../stores/LifecycleStore'); +import '../../stores/LifecycleStore'; +// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss +import 'focus-visible'; import PageTypes from '../../PageTypes'; import { getHomePageUrl } from '../../utils/pages'; diff --git a/src/components/views/context_menus/TopLeftMenu.js b/src/components/views/context_menus/TopLeftMenu.js index 09e9142201..4080ebf5bf 100644 --- a/src/components/views/context_menus/TopLeftMenu.js +++ b/src/components/views/context_menus/TopLeftMenu.js @@ -24,6 +24,7 @@ import Modal from "../../../Modal"; import SdkConfig from '../../../SdkConfig'; import { getHostingLink } from '../../../utils/HostingLink'; import MatrixClientPeg from '../../../MatrixClientPeg'; +import sdk from "../../../index"; export class TopLeftMenu extends React.Component { static propTypes = { @@ -57,6 +58,8 @@ export class TopLeftMenu extends React.Component { } render() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + const isGuest = MatrixClientPeg.get().isGuest(); const hostingSignupLink = getHostingLink('user-context-menu'); @@ -77,25 +80,33 @@ export class TopLeftMenu extends React.Component { let homePageItem = null; if (this.hasHomePage()) { - homePageItem =
  • - {_t("Home")} -
  • ; + homePageItem = ( + + {_t("Home")} + + ); } let signInOutItem; if (isGuest) { - signInOutItem =
  • - {_t("Sign in")} -
  • ; + signInOutItem = ( + + {_t("Sign in")} + + ); } else { - signInOutItem =
  • - {_t("Sign out")} -
  • ; + signInOutItem = ( + + {_t("Sign out")} + + ); } - const settingsItem =
  • - {_t("Settings")} -
  • ; + const settingsItem = ( + + {_t("Settings")} + + ); return
    diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.js index 1797065f11..2b43c5fe2a 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.js @@ -140,6 +140,8 @@ export default class MessageActionBar extends React.PureComponent { } render() { + const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); + let reactButton; let replyButton; let editButton; @@ -149,14 +151,16 @@ export default class MessageActionBar extends React.PureComponent { reactButton = this.renderReactButton(); } if (this.context.room.canReply) { - replyButton = ; } } if (canEditContent(this.props.mxEvent)) { - editButton = ; @@ -166,7 +170,7 @@ export default class MessageActionBar extends React.PureComponent { {reactButton} {replyButton} {editButton} - Date: Fri, 27 Sep 2019 09:14:29 +0100 Subject: [PATCH 6/7] delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/elements/_AccessibleButton.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 0cf1a78c4f..f3afef284f 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -18,7 +18,7 @@ limitations under the License. cursor: pointer; } -.mx_AccessibleButton:focus:not(.focus-visible) { +.mx_AccessibleButton:focus:not(.focus-visible) { outline: 0; } From ce78de2185603632b354d886859ecc133ce149c1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 27 Sep 2019 10:05:08 +0100 Subject: [PATCH 7/7] re-order imports Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index dccc7be2f1..6a03941bd9 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -24,6 +24,9 @@ import createReactClass from 'create-react-class'; import PropTypes from 'prop-types'; import Matrix from "matrix-js-sdk"; +// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss +import 'focus-visible'; + import Analytics from "../../Analytics"; import { DecryptionFailureTracker } from "../../DecryptionFailureTracker"; import MatrixClientPeg from "../../MatrixClientPeg"; @@ -42,8 +45,6 @@ import linkifyMatrix from "../../linkify-matrix"; import * as Lifecycle from '../../Lifecycle'; // LifecycleStore is not used but does listen to and dispatch actions import '../../stores/LifecycleStore'; -// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss -import 'focus-visible'; import PageTypes from '../../PageTypes'; import { getHomePageUrl } from '../../utils/pages';