Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Correct accessibility labels for unread rooms in spotlight (#9003)
Browse files Browse the repository at this point in the history
* Correct accessibility labels for unread rooms in spotlight
* Improve public room result accessibility
* Improve room result accessibility
  • Loading branch information
justjanne authored Jul 11, 2022
1 parent 375ff26 commit a9d6896
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 98 deletions.
8 changes: 2 additions & 6 deletions src/components/views/dialogs/ForwardDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ import BaseAvatar from "../avatars/BaseAvatar";
import { Action } from "../../../dispatcher/actions";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { ButtonEvent } from "../elements/AccessibleButton";
import { roomContextDetailsText } from "../../../utils/i18n-helpers";
import { isLocationEvent } from "../../../utils/EventUtils";
import { isSelfLocation, locationEventGeoUri } from "../../../utils/location";
import { RoomContextDetails } from "../rooms/RoomContextDetails";

const AVATAR_SIZE = 30;

Expand Down Expand Up @@ -130,8 +130,6 @@ const Entry: React.FC<IEntryProps> = ({ room, type, content, matrixClient: cli,
/>;
}

const detailsText = roomContextDetailsText(room);

return <div className="mx_ForwardList_entry">
<AccessibleTooltipButton
className="mx_ForwardList_roomButton"
Expand All @@ -141,9 +139,7 @@ const Entry: React.FC<IEntryProps> = ({ room, type, content, matrixClient: cli,
>
<DecoratedRoomAvatar room={room} avatarSize={32} />
<span className="mx_ForwardList_entry_name">{ room.name }</span>
{ detailsText && <span className="mx_ForwardList_entry_detail">
{ detailsText }
</span> }
<RoomContextDetails component="span" className="mx_ForwardList_entry_detail" room={room} />
</AccessibleTooltipButton>
<AccessibleTooltipButton
kind={sendState === SendState.Failed ? "danger_outline" : "primary_outline"}
Expand Down
15 changes: 11 additions & 4 deletions src/components/views/dialogs/spotlight/PublicRoomResultDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ import { getDisplayAliasForRoom } from "../../../structures/RoomDirectory";
const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 800;

export function PublicRoomResultDetails({ room }: { room: IPublicRoomsChunkRoom }): JSX.Element {
interface Props {
room: IPublicRoomsChunkRoom;
labelId: string;
descriptionId: string;
detailsId: string;
}

export function PublicRoomResultDetails({ room, labelId, descriptionId, detailsId }: Props): JSX.Element {
let name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
if (name.length > MAX_NAME_LENGTH) {
name = `${name.substring(0, MAX_NAME_LENGTH)}...`;
Expand All @@ -41,12 +48,12 @@ export function PublicRoomResultDetails({ room }: { room: IPublicRoomsChunkRoom
return (
<div className="mx_SpotlightDialog_result_publicRoomDetails">
<div className="mx_SpotlightDialog_result_publicRoomHeader">
<span className="mx_SpotlightDialog_result_publicRoomName">{ name }</span>
<span className="mx_SpotlightDialog_result_publicRoomAlias">
<span id={labelId} className="mx_SpotlightDialog_result_publicRoomName">{ name }</span>
<span id={descriptionId} className="mx_SpotlightDialog_result_publicRoomAlias">
{ room.canonical_alias ?? room.room_id }
</span>
</div>
<div className="mx_SpotlightDialog_result_publicRoomDescription">
<div id={detailsId} className="mx_SpotlightDialog_result_publicRoomDescription">
<span className="mx_SpotlightDialog_result_publicRoomMemberCount">
{ _t("%(count)s Members", {
count: room.num_joined_members,
Expand Down
194 changes: 152 additions & 42 deletions src/components/views/dialogs/spotlight/SpotlightDialog.tsx

Large diffs are not rendered by default.

8 changes: 2 additions & 6 deletions src/components/views/rooms/RecentlyViewedButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import { MenuItem } from "../../structures/ContextMenu";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import { _t } from "../../../languageHandler";
import dis from "../../../dispatcher/dispatcher";
import { RoomContextDetails } from "./RoomContextDetails";
import InteractiveTooltip, { Direction } from "../elements/InteractiveTooltip";
import { Action } from "../../../dispatcher/actions";
import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar";
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
import { roomContextDetailsText } from "../../../utils/i18n-helpers";
import RoomAvatar from "../avatars/RoomAvatar";

const RecentlyViewedButton = () => {
Expand All @@ -37,8 +37,6 @@ const RecentlyViewedButton = () => {
<h4>{ _t("Recently viewed") }</h4>
<div>
{ crumbs.map(crumb => {
const contextDetails = roomContextDetailsText(crumb);

return <MenuItem
key={crumb.roomId}
onClick={(ev) => {
Expand All @@ -57,9 +55,7 @@ const RecentlyViewedButton = () => {
}
<span className="mx_RecentlyViewedButton_entry_label">
<div>{ crumb.name }</div>
{ contextDetails && <div className="mx_RecentlyViewedButton_entry_spaces">
{ contextDetails }
</div> }
<RoomContextDetails className="mx_RecentlyViewedButton_entry_spaces" room={crumb} />
</span>
</MenuItem>;
}) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,26 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React from "react";
import { Room } from "matrix-js-sdk/src/matrix";
import React, { ComponentPropsWithoutRef, ElementType } from "react";

import { roomContextDetailsText, spaceContextDetailsText } from "../../../../utils/i18n-helpers";
import { roomContextDetails } from "../../../utils/i18n-helpers";

export const RoomResultDetails = ({ room }: { room: Room }) => {
const contextDetails = room.isSpaceRoom() ? spaceContextDetailsText(room) : roomContextDetailsText(room);
type Props<T extends ElementType> = ComponentPropsWithoutRef<T> & {
component?: T;
room: Room;
};

export function RoomContextDetails<T extends ElementType>({ room, component: Component = "div", ...other }: Props<T>) {
const contextDetails = roomContextDetails(room);
if (contextDetails) {
return <div className="mx_SpotlightDialog_result_details">
{ contextDetails }
</div>;
return <Component
{...other}
aria-label={contextDetails.ariaLabel}
>
{ contextDetails.details }
</Component>;
}

return null;
};
}
4 changes: 4 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -661,9 +661,13 @@
"about a day from now": "about a day from now",
"%(num)s days from now": "%(num)s days from now",
"%(space1Name)s and %(space2Name)s": "%(space1Name)s and %(space2Name)s",
"In spaces %(space1Name)s and %(space2Name)s.": "In spaces %(space1Name)s and %(space2Name)s.",
"%(spaceName)s and %(count)s others|other": "%(spaceName)s and %(count)s others",
"%(spaceName)s and %(count)s others|zero": "%(spaceName)s",
"%(spaceName)s and %(count)s others|one": "%(spaceName)s and %(count)s other",
"In %(spaceName)s and %(count)s other spaces.|other": "In %(spaceName)s and %(count)s other spaces.",
"In %(spaceName)s and %(count)s other spaces.|zero": "In space %(spaceName)s.",
"In %(spaceName)s and %(count)s other spaces.|one": "In %(spaceName)s and %(count)s other space.",
"%(name)s (%(userId)s)": "%(name)s (%(userId)s)",
"Unexpected server error trying to leave the room": "Unexpected server error trying to leave the room",
"Can't leave Server Notices room": "Can't leave Server Notices room",
Expand Down
51 changes: 19 additions & 32 deletions src/utils/i18n-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,49 +20,36 @@ import SpaceStore from "../stores/spaces/SpaceStore";
import { _t } from "../languageHandler";
import DMRoomMap from "./DMRoomMap";

export function spaceContextDetailsText(space: Room): string {
if (!space.isSpaceRoom()) return undefined;

const [parent, secondParent, ...otherParents] = SpaceStore.instance.getKnownParents(space.roomId);
if (secondParent && !otherParents?.length) {
// exactly 2 edge case for improved i18n
return _t("%(space1Name)s and %(space2Name)s", {
space1Name: space.client.getRoom(parent)?.name,
space2Name: space.client.getRoom(secondParent)?.name,
});
} else if (parent) {
return _t("%(spaceName)s and %(count)s others", {
spaceName: space.client.getRoom(parent)?.name,
count: otherParents.length,
});
}

return space.getCanonicalAlias();
export interface RoomContextDetails {
details: string;
ariaLabel?: string;
}

export function roomContextDetailsText(room: Room): string {
if (room.isSpaceRoom()) return undefined;

export function roomContextDetails(room: Room): RoomContextDetails | null {
const dmPartner = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
// if we’ve got more than 2 users, don’t treat it like a regular DM
const isGroupDm = room.getMembers().length > 2;
if (dmPartner && !isGroupDm) {
return dmPartner;
if (!room.isSpaceRoom() && dmPartner && !isGroupDm) {
return { details: dmPartner };
}

const [parent, secondParent, ...otherParents] = SpaceStore.instance.getKnownParents(room.roomId);
if (secondParent && !otherParents?.length) {
// exactly 2 edge case for improved i18n
return _t("%(space1Name)s and %(space2Name)s", {
space1Name: room.client.getRoom(parent)?.name,
space2Name: room.client.getRoom(secondParent)?.name,
});
const space1Name = room.client.getRoom(parent)?.name;
const space2Name = room.client.getRoom(secondParent)?.name;
return {
details: _t("%(space1Name)s and %(space2Name)s", { space1Name, space2Name }),
ariaLabel: _t("In spaces %(space1Name)s and %(space2Name)s.", { space1Name, space2Name }),
};
} else if (parent) {
return _t("%(spaceName)s and %(count)s others", {
spaceName: room.client.getRoom(parent)?.name,
count: otherParents.length,
});
const spaceName = room.client.getRoom(parent)?.name;
const count = otherParents.length;
return {
details: _t("%(spaceName)s and %(count)s others", { spaceName, count }),
ariaLabel: _t("In %(spaceName)s and %(count)s other spaces.", { spaceName, count }),
};
}

return room.getCanonicalAlias();
return { details: room.getCanonicalAlias() };
}

0 comments on commit a9d6896

Please sign in to comment.