Proper accessible buttons

This commit is contained in:
Jani Mustonen 2017-01-13 18:25:26 +02:00
parent 041196d729
commit 959163f2ef
10 changed files with 51 additions and 39 deletions

View file

@ -26,6 +26,7 @@ var UserSettingsStore = require('../../UserSettingsStore');
var GeminiScrollbar = require('react-gemini-scrollbar'); var GeminiScrollbar = require('react-gemini-scrollbar');
var Email = require('../../email'); var Email = require('../../email');
var AddThreepid = require('../../AddThreepid'); var AddThreepid = require('../../AddThreepid');
var AccessibleButton = require('../views/elements/AccessibleButton');
// if this looks like a release, use the 'version' from package.json; else use // if this looks like a release, use the 'version' from package.json; else use
// the git sha. // the git sha.
@ -470,9 +471,9 @@ module.exports = React.createClass({
return <div> return <div>
<h3>Deactivate Account</h3> <h3>Deactivate Account</h3>
<div className="mx_UserSettings_section"> <div className="mx_UserSettings_section">
<button className="mx_UserSettings_button danger" <AccessibleButton className="mx_UserSettings_button danger"
onClick={this._onDeactivateAccountClicked}>Deactivate my account onClick={this._onDeactivateAccountClicked}>Deactivate my account
</button> </AccessibleButton>
</div> </div>
</div>; </div>;
}, },
@ -492,10 +493,10 @@ module.exports = React.createClass({
// bind() the invited rooms so any new invites that may come in as this button is clicked // bind() the invited rooms so any new invites that may come in as this button is clicked
// don't inadvertently get rejected as well. // don't inadvertently get rejected as well.
reject = ( reject = (
<button className="mx_UserSettings_button danger" <AccessibleButton className="mx_UserSettings_button danger"
onClick={this._onRejectAllInvitesClicked.bind(this, invitedRooms)}> onClick={this._onRejectAllInvitesClicked.bind(this, invitedRooms)}>
Reject all {invitedRooms.length} invites Reject all {invitedRooms.length} invites
</button> </AccessibleButton>
); );
} }
@ -663,9 +664,9 @@ module.exports = React.createClass({
<div className="mx_UserSettings_section"> <div className="mx_UserSettings_section">
<button className="mx_UserSettings_logout mx_UserSettings_button" onClick={this.onLogoutClicked}> <AccessibleButton className="mx_UserSettings_logout mx_UserSettings_button" onClick={this.onLogoutClicked}>
Sign out Sign out
</button> </AccessibleButton>
{accountJsx} {accountJsx}
</div> </div>

View file

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react'); var React = require('react');
var AvatarLogic = require("../../../Avatar"); var AvatarLogic = require("../../../Avatar");
import sdk from '../../../index'; import sdk from '../../../index';
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'BaseAvatar', displayName: 'BaseAvatar',
@ -158,13 +159,13 @@ module.exports = React.createClass({
} }
if (onClick != null) { if (onClick != null) {
return ( return (
<button className="mx_BaseAvatar" onClick={onClick}> <AccessibleButton className="mx_BaseAvatar" onClick={onClick}>
<img className="mx_BaseAvatar_image" src={imageUrl} <img className="mx_BaseAvatar_image" src={imageUrl}
onError={this.onError} onError={this.onError}
width={width} height={height} width={width} height={height}
title={title} alt="" title={title} alt=""
{...otherProps} /> {...otherProps} />
</button> </AccessibleButton>
); );
} else { } else {
return ( return (

View file

@ -24,6 +24,7 @@ var DMRoomMap = require('../../../utils/DMRoomMap');
var rate_limited_func = require("../../../ratelimitedfunc"); var rate_limited_func = require("../../../ratelimitedfunc");
var dis = require("../../../dispatcher"); var dis = require("../../../dispatcher");
var Modal = require('../../../Modal'); var Modal = require('../../../Modal');
var AccessibleButton = require('../elements/AccessibleButton');
const TRUNCATE_QUERY_LIST = 40; const TRUNCATE_QUERY_LIST = 40;
@ -409,9 +410,9 @@ module.exports = React.createClass({
<div className="mx_Dialog_title"> <div className="mx_Dialog_title">
{this.props.title} {this.props.title}
</div> </div>
<button className="mx_ChatInviteDialog_cancel" onClick={this.onCancel} > <AccessibleButton className="mx_ChatInviteDialog_cancel" onClick={this.onCancel} >
<TintableSvg src="img/icons-close-button.svg" width="35" height="35" /> <TintableSvg src="img/icons-close-button.svg" width="35" height="35" />
</button> </AccessibleButton>
<div className="mx_ChatInviteDialog_label"> <div className="mx_ChatInviteDialog_label">
<label htmlFor="textinput">{ this.props.description }</label> <label htmlFor="textinput">{ this.props.description }</label>
</div> </div>

View file

@ -20,6 +20,7 @@ var React = require('react');
var MatrixClientPeg = require('../../../MatrixClientPeg'); var MatrixClientPeg = require('../../../MatrixClientPeg');
var sdk = require('../../../index'); var sdk = require('../../../index');
var AccessibleButton = require('../elements/AccessibleButton');
var PRESENCE_CLASS = { var PRESENCE_CLASS = {
@ -152,7 +153,7 @@ module.exports = React.createClass({
var av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />; var av = this.props.avatarJsx || <BaseAvatar name={this.props.name} width={36} height={36} />;
return ( return (
<button className={mainClassName} title={ this.props.title } <AccessibleButton className={mainClassName} title={ this.props.title }
onClick={ this.props.onClick } onMouseEnter={ this.mouseEnter } onClick={ this.props.onClick } onMouseEnter={ this.mouseEnter }
onMouseLeave={ this.mouseLeave }> onMouseLeave={ this.mouseLeave }>
<div className="mx_EntityTile_avatar"> <div className="mx_EntityTile_avatar">
@ -161,7 +162,7 @@ module.exports = React.createClass({
</div> </div>
{ nameEl } { nameEl }
{ inviteButton } { inviteButton }
</button> </AccessibleButton>
); );
} }
}); });

View file

@ -35,6 +35,7 @@ var DMRoomMap = require('../../../utils/DMRoomMap');
var Unread = require('../../../Unread'); var Unread = require('../../../Unread');
var Receipt = require('../../../utils/Receipt'); var Receipt = require('../../../utils/Receipt');
var WithMatrixClient = require('../../../wrappers/WithMatrixClient'); var WithMatrixClient = require('../../../wrappers/WithMatrixClient');
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = WithMatrixClient(React.createClass({ module.exports = WithMatrixClient(React.createClass({
displayName: 'MemberInfo', displayName: 'MemberInfo',
@ -612,7 +613,7 @@ module.exports = WithMatrixClient(React.createClass({
mx_MemberInfo_createRoom_label: true, mx_MemberInfo_createRoom_label: true,
mx_RoomTile_name: true, mx_RoomTile_name: true,
}); });
const startNewChat = <button const startNewChat = <AccessibleButton
className="mx_MemberInfo_createRoom" className="mx_MemberInfo_createRoom"
onClick={this.onNewDMClick} onClick={this.onNewDMClick}
> >
@ -620,7 +621,7 @@ module.exports = WithMatrixClient(React.createClass({
<img src="img/create-big.svg" width="26" height="26" /> <img src="img/create-big.svg" width="26" height="26" />
</div> </div>
<div className={labelClasses}><i>Start new chat</i></div> <div className={labelClasses}><i>Start new chat</i></div>
</button> </AccessibleButton>
startChat = <div> startChat = <div>
<h3>Direct chats</h3> <h3>Direct chats</h3>
@ -635,26 +636,26 @@ module.exports = WithMatrixClient(React.createClass({
} }
if (this.state.can.kick) { if (this.state.can.kick) {
kickButton = <button className="mx_MemberInfo_field" onClick={this.onKick}> kickButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onKick}>
{ this.props.member.membership === "invite" ? "Disinvite" : "Kick" } { this.props.member.membership === "invite" ? "Disinvite" : "Kick" }
</button>; </AccessibleButton>;
} }
if (this.state.can.ban) { if (this.state.can.ban) {
banButton = <button className="mx_MemberInfo_field" onClick={this.onBan}> banButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onBan}>
Ban Ban
</button>; </AccessibleButton>;
} }
if (this.state.can.mute) { if (this.state.can.mute) {
var muteLabel = this.state.muted ? "Unmute" : "Mute"; var muteLabel = this.state.muted ? "Unmute" : "Mute";
muteButton = <button className="mx_MemberInfo_field" onClick={this.onMuteToggle}> muteButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onMuteToggle}>
{muteLabel} {muteLabel}
</button>; </AccessibleButton>;
} }
if (this.state.can.toggleMod) { if (this.state.can.toggleMod) {
var giveOpLabel = this.state.isTargetMod ? "Revoke Moderator" : "Make Moderator"; var giveOpLabel = this.state.isTargetMod ? "Revoke Moderator" : "Make Moderator";
giveModButton = <button className="mx_MemberInfo_field" onClick={this.onModToggle}> giveModButton = <AccessibleButton className="mx_MemberInfo_field" onClick={this.onModToggle}>
{giveOpLabel} {giveOpLabel}
</button> </AccessibleButton>
} }
// TODO: we should have an invite button if this MemberInfo is showing a user who isn't actually in the current room yet // TODO: we should have an invite button if this MemberInfo is showing a user who isn't actually in the current room yet
@ -682,7 +683,7 @@ module.exports = WithMatrixClient(React.createClass({
const EmojiText = sdk.getComponent('elements.EmojiText'); const EmojiText = sdk.getComponent('elements.EmojiText');
return ( return (
<div className="mx_MemberInfo"> <div className="mx_MemberInfo">
<button className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18"/></button> <AccessibleButton className="mx_MemberInfo_cancel" onClick={this.onCancel}> <img src="img/cancel.svg" width="18" height="18"/></AccessibleButton>
<div className="mx_MemberInfo_avatar"> <div className="mx_MemberInfo_avatar">
<MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} /> <MemberAvatar onClick={this.onMemberAvatarClick} member={this.props.member} width={48} height={48} />
</div> </div>

View file

@ -192,9 +192,9 @@ module.exports = React.createClass({
width={14} height={14} resizeMethod="crop" width={14} height={14} resizeMethod="crop"
style={style} style={style}
title={title} title={title}
onClick={this.props.onClick}
/> />
</Velociraptor> </Velociraptor>
); );
/* onClick={this.props.onClick} */
}, },
}); });

View file

@ -26,6 +26,7 @@ var rate_limited_func = require('../../../ratelimitedfunc');
var linkify = require('linkifyjs'); var linkify = require('linkifyjs');
var linkifyElement = require('linkifyjs/element'); var linkifyElement = require('linkifyjs/element');
var linkifyMatrix = require('../../../linkify-matrix'); var linkifyMatrix = require('../../../linkify-matrix');
var AccessibleButton = require('../elements/AccessibleButton');
linkifyMatrix(linkify); linkifyMatrix(linkify);
@ -182,8 +183,8 @@ module.exports = React.createClass({
'm.room.name', user_id 'm.room.name', user_id
); );
save_button = <button className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</button> save_button = <AccessibleButton className="mx_RoomHeader_textButton" onClick={this.props.onSaveClick}>Save</AccessibleButton>
cancel_button = <button className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </button> cancel_button = <AccessibleButton className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </AccessibleButton>
} }
if (this.props.saving) { if (this.props.saving) {
@ -275,9 +276,9 @@ module.exports = React.createClass({
var settings_button; var settings_button;
if (this.props.onSettingsClick) { if (this.props.onSettingsClick) {
settings_button = settings_button =
<button className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title="Settings"> <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSettingsClick} title="Settings">
<TintableSvg src="img/icons-settings-room.svg" width="16" height="16"/> <TintableSvg src="img/icons-settings-room.svg" width="16" height="16"/>
</button>; </AccessibleButton>;
} }
// var leave_button; // var leave_button;
@ -291,17 +292,17 @@ module.exports = React.createClass({
var forget_button; var forget_button;
if (this.props.onForgetClick) { if (this.props.onForgetClick) {
forget_button = forget_button =
<button className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room"> <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onForgetClick} title="Forget room">
<TintableSvg src="img/leave.svg" width="26" height="20"/> <TintableSvg src="img/leave.svg" width="26" height="20"/>
</button>; </AccessibleButton>;
} }
var rightPanel_buttons; var rightPanel_buttons;
if (this.props.collapsedRhs) { if (this.props.collapsedRhs) {
rightPanel_buttons = rightPanel_buttons =
<button className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="<"> <AccessibleButton className="mx_RoomHeader_button" onClick={this.onShowRhsClick} title="<">
<TintableSvg src="img/minimise.svg" width="10" height="16"/> <TintableSvg src="img/minimise.svg" width="10" height="16"/>
</button> </AccessibleButton>
} }
var right_row; var right_row;
@ -310,9 +311,9 @@ module.exports = React.createClass({
<div className="mx_RoomHeader_rightRow"> <div className="mx_RoomHeader_rightRow">
{ settings_button } { settings_button }
{ forget_button } { forget_button }
<button className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search"> <AccessibleButton className="mx_RoomHeader_button" onClick={this.props.onSearchClick} title="Search">
<TintableSvg src="img/icons-search.svg" width="35" height="35"/> <TintableSvg src="img/icons-search.svg" width="35" height="35"/>
</button> </AccessibleButton>
{ rightPanel_buttons } { rightPanel_buttons }
</div>; </div>;
} }

View file

@ -26,6 +26,7 @@ var sdk = require('../../../index');
var ContextualMenu = require('../../structures/ContextualMenu'); var ContextualMenu = require('../../structures/ContextualMenu');
var RoomNotifs = require('../../../RoomNotifs'); var RoomNotifs = require('../../../RoomNotifs');
var FormattingUtils = require('../../../utils/FormattingUtils'); var FormattingUtils = require('../../../utils/FormattingUtils');
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'RoomTile', displayName: 'RoomTile',
@ -286,8 +287,10 @@ module.exports = React.createClass({
var connectDragSource = this.props.connectDragSource; var connectDragSource = this.props.connectDragSource;
var connectDropTarget = this.props.connectDropTarget; var connectDropTarget = this.props.connectDropTarget;
let ret = ( let ret = (
<button className={classes} tabIndex="0" onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}> <div> { /* Only native elements can be wrapped in a DnD object. */}
<AccessibleButton className={classes} tabIndex="0" onClick={this.onClick} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<div className={avatarClasses}> <div className={avatarClasses}>
<div className="mx_RoomTile_avatar_menu" onClick={this.onAvatarClicked}> <div className="mx_RoomTile_avatar_menu" onClick={this.onAvatarClicked}>
<div className={avatarContainerClasses}> <div className={avatarContainerClasses}>
@ -302,7 +305,8 @@ module.exports = React.createClass({
</div> </div>
{/* { incomingCallBox } */} {/* { incomingCallBox } */}
{ tooltip } { tooltip }
</button> </AccessibleButton>
</div>
); );
if (connectDropTarget) ret = connectDropTarget(ret); if (connectDropTarget) ret = connectDropTarget(ret);

View file

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react'); var React = require('react');
var sdk = require('../../../index'); var sdk = require('../../../index');
var dis = require("../../../dispatcher"); var dis = require("../../../dispatcher");
var AccessibleButton = require('../elements/AccessibleButton');
/* /*
* A stripped-down room header used for things like the user settings * A stripped-down room header used for things like the user settings
@ -44,7 +45,7 @@ module.exports = React.createClass({
var cancelButton; var cancelButton;
if (this.props.onCancelClick) { if (this.props.onCancelClick) {
cancelButton = <button className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </button> cancelButton = <AccessibleButton className="mx_RoomHeader_cancelButton" onClick={this.props.onCancelClick}><img src="img/cancel.svg" width="18" height="18" alt="Cancel"/> </AccessibleButton>
} }
var showRhsButton; var showRhsButton;

View file

@ -19,6 +19,7 @@ limitations under the License.
var React = require('react'); var React = require('react');
var MatrixClientPeg = require("../../../MatrixClientPeg"); var MatrixClientPeg = require("../../../MatrixClientPeg");
var sdk = require("../../../index"); var sdk = require("../../../index");
var AccessibleButton = require('../elements/AccessibleButton');
module.exports = React.createClass({ module.exports = React.createClass({
displayName: 'ChangePassword', displayName: 'ChangePassword',
@ -136,9 +137,9 @@ module.exports = React.createClass({
<input id="password2" type="password" ref="confirm_input" /> <input id="password2" type="password" ref="confirm_input" />
</div> </div>
</div> </div>
<button className={buttonClassName} onClick={this.onClickChange}> <AccessibleButton className={buttonClassName} onClick={this.onClickChange}>
Change Password Change Password
</button> </AccessibleButton>
</div> </div>
); );
case this.Phases.Uploading: case this.Phases.Uploading: