Improve new room header accessibility (#12725)

* Fix room header topic not showing on keyboard navigation whilst still using tabstops

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix keyboard activation of the room header FacePile

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix label on room header facepile

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Comment

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update src/components/views/elements/FacePile.tsx

Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
pull/28217/head
Michael Telatynski 2024-07-08 12:52:26 +01:00 committed by GitHub
parent b2a89151e6
commit 466f37a83d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 24 deletions

View File

@ -74,14 +74,17 @@ limitations under the License.
} }
} }
.mx_RoomHeader:hover .mx_RoomHeader_topic { .mx_RoomHeader:hover,
/* height needed to compute the transition, it equals to the `line-height` .mx_RoomHeader:focus-within {
.mx_RoomHeader_topic {
/* height needed to compute the transition, it equals to the `line-height`
value in pixels */ value in pixels */
height: calc($font-13px * 1.5); height: calc($font-13px * 1.5);
opacity: 1; opacity: 1;
a:hover { a:hover {
text-decoration: underline; text-decoration: underline;
}
} }
} }

View File

@ -21,7 +21,7 @@ import { AvatarStack, Tooltip } from "@vector-im/compound-web";
import MemberAvatar from "../avatars/MemberAvatar"; import MemberAvatar from "../avatars/MemberAvatar";
import AccessibleButton, { ButtonEvent } from "./AccessibleButton"; import AccessibleButton, { ButtonEvent } from "./AccessibleButton";
interface IProps extends HTMLAttributes<HTMLSpanElement> { interface IProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange"> {
members: RoomMember[]; members: RoomMember[];
size: string; size: string;
overflow: boolean; overflow: boolean;
@ -32,6 +32,11 @@ interface IProps extends HTMLAttributes<HTMLSpanElement> {
onClick?: (e: ButtonEvent) => void | Promise<void>; onClick?: (e: ButtonEvent) => void | Promise<void>;
} }
/**
* A component which displays a list of avatars in a row, with a tooltip showing the names of the users.
*
* Any additional props, not named explicitly here, are passed to the underlying {@link AccessibleButton}.
*/
const FacePile: FC<IProps> = ({ const FacePile: FC<IProps> = ({
members, members,
size, size,
@ -40,6 +45,7 @@ const FacePile: FC<IProps> = ({
tooltipShortcut, tooltipShortcut,
children, children,
viewUserOnClick = true, viewUserOnClick = true,
onClick,
...props ...props
}) => { }) => {
const faces = members.map( const faces = members.map(
@ -47,12 +53,7 @@ const FacePile: FC<IProps> = ({
? (m) => <MemberAvatar key={m.userId} member={m} size={size} hideTitle /> ? (m) => <MemberAvatar key={m.userId} member={m} size={size} hideTitle />
: (m) => ( : (m) => (
<Tooltip key={m.userId} label={m.name} caption={tooltipShortcut}> <Tooltip key={m.userId} label={m.name} caption={tooltipShortcut}>
<MemberAvatar <MemberAvatar member={m} size={size} viewUserOnClick={!onClick && viewUserOnClick} hideTitle />
member={m}
size={size}
viewUserOnClick={!props.onClick && viewUserOnClick}
hideTitle
/>
</Tooltip> </Tooltip>
), ),
); );
@ -65,7 +66,7 @@ const FacePile: FC<IProps> = ({
); );
const content = ( const content = (
<AccessibleButton className="mx_FacePile" onClick={props.onClick ?? null}> <AccessibleButton {...props} className="mx_FacePile" onClick={onClick ?? null}>
<AvatarStack>{pileContents}</AvatarStack> <AvatarStack>{pileContents}</AvatarStack>
{children} {children}
</AccessibleButton> </AccessibleButton>

View File

@ -55,6 +55,7 @@ import { RoomKnocksBar } from "./RoomKnocksBar";
import { isVideoRoom } from "../../../utils/video-rooms"; import { isVideoRoom } from "../../../utils/video-rooms";
import { notificationLevelToIndicator } from "../../../utils/notifications"; import { notificationLevelToIndicator } from "../../../utils/notifications";
import { CallGuestLinkButton } from "./RoomHeader/CallGuestLinkButton"; import { CallGuestLinkButton } from "./RoomHeader/CallGuestLinkButton";
import { ButtonEvent } from "../elements/AccessibleButton";
export default function RoomHeader({ export default function RoomHeader({
room, room,
@ -364,16 +365,7 @@ export default function RoomHeader({
)} )}
</Flex> </Flex>
{!isDirectMessage && ( {!isDirectMessage && (
<BodyText <BodyText as="div" size="sm" weight="medium">
as="div"
size="sm"
weight="medium"
aria-label={_t("common|n_members", { count: memberCount })}
onClick={(e: React.MouseEvent) => {
RightPanelStore.instance.showOrHidePanel(RightPanelPhases.RoomMemberList);
e.stopPropagation();
}}
>
<FacePile <FacePile
className="mx_RoomHeader_members" className="mx_RoomHeader_members"
members={members.slice(0, 3)} members={members.slice(0, 3)}
@ -381,6 +373,11 @@ export default function RoomHeader({
overflow={false} overflow={false}
viewUserOnClick={false} viewUserOnClick={false}
tooltipLabel={_t("room|header_face_pile_tooltip")} tooltipLabel={_t("room|header_face_pile_tooltip")}
onClick={(e: ButtonEvent) => {
RightPanelStore.instance.showOrHidePanel(RightPanelPhases.RoomMemberList);
e.stopPropagation();
}}
aria-label={_t("common|n_members", { count: memberCount })}
> >
{formatCount(memberCount)} {formatCount(memberCount)}
</FacePile> </FacePile>