Sprinkle in some better ARIA props
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
4c7014167d
commit
1620feb55e
5 changed files with 55 additions and 19 deletions
|
@ -235,7 +235,12 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
private renderSearchExplore(): React.ReactNode {
|
private renderSearchExplore(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
<div className="mx_LeftPanel2_filterContainer" onFocus={this.onFocus} onBlur={this.onBlur}>
|
<div
|
||||||
|
className="mx_LeftPanel2_filterContainer"
|
||||||
|
onFocus={this.onFocus}
|
||||||
|
onBlur={this.onBlur}
|
||||||
|
onKeyDown={this.onKeyDown}
|
||||||
|
>
|
||||||
<RoomSearch
|
<RoomSearch
|
||||||
onQueryUpdate={this.onSearch}
|
onQueryUpdate={this.onSearch}
|
||||||
isMinimized={this.props.isMinimized}
|
isMinimized={this.props.isMinimized}
|
||||||
|
@ -245,7 +250,7 @@ export default class LeftPanel2 extends React.Component<IProps, IState> {
|
||||||
// TODO fix the accessibility of this: https://github.com/vector-im/riot-web/issues/14180
|
// TODO fix the accessibility of this: https://github.com/vector-im/riot-web/issues/14180
|
||||||
className="mx_LeftPanel2_exploreButton"
|
className="mx_LeftPanel2_exploreButton"
|
||||||
onClick={this.onExplore}
|
onClick={this.onExplore}
|
||||||
alt={_t("Explore rooms")}
|
title={_t("Explore rooms")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -149,7 +149,8 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
|
||||||
let clearButton = (
|
let clearButton = (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className='mx_RoomSearch_clearButton'
|
title={_t("Clear filter")}
|
||||||
|
className="mx_RoomSearch_clearButton"
|
||||||
onClick={this.clearInput}
|
onClick={this.clearInput}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -157,8 +158,8 @@ export default class RoomSearch extends React.PureComponent<IProps, IState> {
|
||||||
if (this.props.isMinimized) {
|
if (this.props.isMinimized) {
|
||||||
icon = (
|
icon = (
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
tabIndex={-1}
|
title={_t("Search rooms")}
|
||||||
className='mx_RoomSearch_icon'
|
className="mx_RoomSearch_icon"
|
||||||
onClick={this.openSearch}
|
onClick={this.openSearch}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -276,9 +276,6 @@ export default class RoomList2 extends React.Component<IProps, IState> {
|
||||||
className="mx_RoomList2"
|
className="mx_RoomList2"
|
||||||
role="tree"
|
role="tree"
|
||||||
aria-label={_t("Rooms")}
|
aria-label={_t("Rooms")}
|
||||||
// Firefox sometimes makes this element focusable due to
|
|
||||||
// overflow:scroll;, so force it out of tab order.
|
|
||||||
tabIndex={-1}
|
|
||||||
>{sublists}</div>
|
>{sublists}</div>
|
||||||
)}
|
)}
|
||||||
</RovingTabIndexProvider>
|
</RovingTabIndexProvider>
|
||||||
|
|
|
@ -63,7 +63,7 @@ interface IProps {
|
||||||
onAddRoom?: () => void;
|
onAddRoom?: () => void;
|
||||||
addRoomLabel: string;
|
addRoomLabel: string;
|
||||||
isInvite: boolean;
|
isInvite: boolean;
|
||||||
layout: ListLayout;
|
layout?: ListLayout;
|
||||||
isMinimized: boolean;
|
isMinimized: boolean;
|
||||||
tagId: TagID;
|
tagId: TagID;
|
||||||
|
|
||||||
|
@ -203,6 +203,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_room',
|
action: 'view_room',
|
||||||
room_id: room.roomId,
|
room_id: room.roomId,
|
||||||
|
show_room_tile: true, // to make sure the room gets scrolled into view
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -383,16 +384,22 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
private renderHeader(): React.ReactElement {
|
private renderHeader(): React.ReactElement {
|
||||||
return (
|
return (
|
||||||
<RovingTabIndexWrapper>
|
<RovingTabIndexWrapper inputRef={this.headerButton}>
|
||||||
{({onFocus, isActive, ref}) => {
|
{({onFocus, isActive, ref}) => {
|
||||||
const tabIndex = isActive ? 0 : -1;
|
const tabIndex = isActive ? 0 : -1;
|
||||||
|
|
||||||
|
let ariaLabel = _t("Jump to first unread room.");
|
||||||
|
if (this.props.tagId === DefaultTagID.Invite) {
|
||||||
|
ariaLabel = _t("Jump to first invite.");
|
||||||
|
}
|
||||||
|
|
||||||
const badge = (
|
const badge = (
|
||||||
<NotificationBadge
|
<NotificationBadge
|
||||||
forceCount={true}
|
forceCount={true}
|
||||||
notification={this.state.notificationState}
|
notification={this.state.notificationState}
|
||||||
onClick={this.onBadgeClick}
|
onClick={this.onBadgeClick}
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
|
aria-label={ariaLabel}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -433,7 +440,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
// doesn't become sticky.
|
// doesn't become sticky.
|
||||||
// The same applies to the notification badge.
|
// The same applies to the notification badge.
|
||||||
return (
|
return (
|
||||||
<div className={classes} onKeyDown={this.onHeaderKeyDown} onFocus={onFocus}>
|
<div className={classes} onKeyDown={this.onHeaderKeyDown} onFocus={onFocus} aria-label={this.props.label}>
|
||||||
<div className="mx_RoomSublist2_stickable">
|
<div className="mx_RoomSublist2_stickable">
|
||||||
<AccessibleButton
|
<AccessibleButton
|
||||||
onFocus={onFocus}
|
onFocus={onFocus}
|
||||||
|
@ -441,6 +448,7 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
className="mx_RoomSublist2_headerText"
|
className="mx_RoomSublist2_headerText"
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
|
aria-expanded={!this.props.layout || !this.props.layout.isCollapsed}
|
||||||
aria-level={1}
|
aria-level={1}
|
||||||
onClick={this.onHeaderClick}
|
onClick={this.onHeaderClick}
|
||||||
onContextMenu={this.onContextMenu}
|
onContextMenu={this.onContextMenu}
|
||||||
|
@ -496,12 +504,12 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
if (this.props.isMinimized) showMoreText = null;
|
if (this.props.isMinimized) showMoreText = null;
|
||||||
showNButton = (
|
showNButton = (
|
||||||
<div onClick={this.onShowAllClick} className={showMoreBtnClasses}>
|
<AccessibleButton onClick={this.onShowAllClick} className={showMoreBtnClasses} tabIndex={-1}>
|
||||||
<span className='mx_RoomSublist2_showMoreButtonChevron mx_RoomSublist2_showNButtonChevron'>
|
<span className='mx_RoomSublist2_showMoreButtonChevron mx_RoomSublist2_showNButtonChevron'>
|
||||||
{/* set by CSS masking */}
|
{/* set by CSS masking */}
|
||||||
</span>
|
</span>
|
||||||
{showMoreText}
|
{showMoreText}
|
||||||
</div>
|
</AccessibleButton>
|
||||||
);
|
);
|
||||||
} else if (this.numTiles <= visibleTiles.length && this.numTiles > this.props.layout.defaultVisibleTiles) {
|
} else if (this.numTiles <= visibleTiles.length && this.numTiles > this.props.layout.defaultVisibleTiles) {
|
||||||
// we have all tiles visible - add a button to show less
|
// we have all tiles visible - add a button to show less
|
||||||
|
@ -512,12 +520,12 @@ export default class RoomSublist2 extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
if (this.props.isMinimized) showLessText = null;
|
if (this.props.isMinimized) showLessText = null;
|
||||||
showNButton = (
|
showNButton = (
|
||||||
<div onClick={this.onShowLessClick} className={showMoreBtnClasses}>
|
<AccessibleButton onClick={this.onShowLessClick} className={showMoreBtnClasses} tabIndex={-1}>
|
||||||
<span className='mx_RoomSublist2_showLessButtonChevron mx_RoomSublist2_showNButtonChevron'>
|
<span className='mx_RoomSublist2_showLessButtonChevron mx_RoomSublist2_showNButtonChevron'>
|
||||||
{/* set by CSS masking */}
|
{/* set by CSS masking */}
|
||||||
</span>
|
</span>
|
||||||
{showLessText}
|
{showLessText}
|
||||||
</div>
|
</AccessibleButton>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,15 @@ import { ContextMenu, ContextMenuButton, MenuItemRadio } from "../../structures/
|
||||||
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
import { DefaultTagID, TagID } from "../../../stores/room-list/models";
|
||||||
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
||||||
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
|
||||||
import { getRoomNotifsState, ALL_MESSAGES, ALL_MESSAGES_LOUD, MENTIONS_ONLY, MUTE } from "../../../RoomNotifs";
|
import {
|
||||||
|
getRoomNotifsState,
|
||||||
|
setRoomNotifsState,
|
||||||
|
ALL_MESSAGES,
|
||||||
|
ALL_MESSAGES_LOUD,
|
||||||
|
MENTIONS_ONLY,
|
||||||
|
MUTE,
|
||||||
|
} from "../../../RoomNotifs";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import { setRoomNotifsState } from "../../../RoomNotifs";
|
|
||||||
import { TagSpecificNotificationState } from "../../../stores/notifications/TagSpecificNotificationState";
|
import { TagSpecificNotificationState } from "../../../stores/notifications/TagSpecificNotificationState";
|
||||||
import { INotificationState } from "../../../stores/notifications/INotificationState";
|
import { INotificationState } from "../../../stores/notifications/INotificationState";
|
||||||
import NotificationBadge from "./NotificationBadge";
|
import NotificationBadge from "./NotificationBadge";
|
||||||
|
@ -406,10 +412,11 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const notificationColor = this.state.notificationState.color;
|
||||||
const nameClasses = classNames({
|
const nameClasses = classNames({
|
||||||
"mx_RoomTile2_name": true,
|
"mx_RoomTile2_name": true,
|
||||||
"mx_RoomTile2_nameWithPreview": !!messagePreview,
|
"mx_RoomTile2_nameWithPreview": !!messagePreview,
|
||||||
"mx_RoomTile2_nameHasUnreadEvents": this.state.notificationState.color >= NotificationColor.Bold,
|
"mx_RoomTile2_nameHasUnreadEvents": notificationColor >= NotificationColor.Bold,
|
||||||
});
|
});
|
||||||
|
|
||||||
let nameContainer = (
|
let nameContainer = (
|
||||||
|
@ -422,6 +429,22 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
);
|
);
|
||||||
if (this.props.isMinimized) nameContainer = null;
|
if (this.props.isMinimized) nameContainer = null;
|
||||||
|
|
||||||
|
let ariaLabel = name;
|
||||||
|
// The following labels are written in such a fashion to increase screen reader efficiency (speed).
|
||||||
|
if (this.props.tag === DefaultTagID.Invite) {
|
||||||
|
// append nothing
|
||||||
|
} else if (notificationColor >= NotificationColor.Red) {
|
||||||
|
ariaLabel += " " + _t("%(count)s unread messages including mentions.", {
|
||||||
|
count: this.state.notificationState.count,
|
||||||
|
});
|
||||||
|
} else if (notificationColor >= NotificationColor.Grey) {
|
||||||
|
ariaLabel += " " + _t("%(count)s unread messages.", {
|
||||||
|
count: this.state.notificationState.count,
|
||||||
|
});
|
||||||
|
} else if (notificationColor >= NotificationColor.Bold) {
|
||||||
|
ariaLabel += " " + _t("Unread messages.");
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<RovingTabIndexWrapper>
|
<RovingTabIndexWrapper>
|
||||||
|
@ -434,8 +457,10 @@ export default class RoomTile2 extends React.Component<IProps, IState> {
|
||||||
onMouseEnter={this.onTileMouseEnter}
|
onMouseEnter={this.onTileMouseEnter}
|
||||||
onMouseLeave={this.onTileMouseLeave}
|
onMouseLeave={this.onTileMouseLeave}
|
||||||
onClick={this.onTileClick}
|
onClick={this.onTileClick}
|
||||||
role="treeitem"
|
|
||||||
onContextMenu={this.onContextMenu}
|
onContextMenu={this.onContextMenu}
|
||||||
|
role="treeitem"
|
||||||
|
aria-label={ariaLabel}
|
||||||
|
aria-selected={this.state.selected}
|
||||||
>
|
>
|
||||||
{roomAvatar}
|
{roomAvatar}
|
||||||
{nameContainer}
|
{nameContainer}
|
||||||
|
|
Loading…
Reference in a new issue