Enable some oxlint a11y rules & improve keyboard accessibility (#34291)
* Conform to oxlint rule jsx-a11y/role-has-required-aria-props * Conform to oxlint rule jsx-a11y/role-supports-aria-props * Conform to oxlint rule jsx-a11y/interactive-supports-focus * Conform to oxlint rule jsx-a11y/click-events-have-key-events * Update snapshots
This commit is contained in:
@@ -446,6 +446,8 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
||||
<Glass className="mx_Dialog_border">
|
||||
<div className="mx_Dialog">{this.staticModal.elem}</div>
|
||||
</Glass>
|
||||
{/* We break the rule here as this is a mouse-only interaction */}
|
||||
{/* oxlint-disable-next-line jsx-a11y/click-events-have-key-events */}
|
||||
<div
|
||||
data-testid="dialog-background"
|
||||
className="mx_Dialog_background mx_Dialog_staticBackground"
|
||||
@@ -480,6 +482,8 @@ export class ModalManager extends TypedEventEmitter<ModalManagerEvent, HandlerMa
|
||||
<Glass className="mx_Dialog_border">
|
||||
<div className="mx_Dialog">{modal.elem}</div>
|
||||
</Glass>
|
||||
{/* We break the rule here as this is a mouse-only interaction */}
|
||||
{/* oxlint-disable-next-line jsx-a11y/click-events-have-key-events */}
|
||||
<div
|
||||
data-testid="dialog-background"
|
||||
className="mx_Dialog_background"
|
||||
|
||||
@@ -51,6 +51,8 @@ const Toolbar = ({ children, ref, ...props }: IProps): JSX.Element => {
|
||||
return (
|
||||
<RovingTabIndexProvider handleHomeEnd handleLeftRight handleUpDown onKeyDown={onKeyDown}>
|
||||
{({ onKeyDownHandler }) => (
|
||||
// This may be wrong but seems to work, this is a roving-toolbar, so the focus follows one of the children
|
||||
// oxlint-disable-next-line jsx-a11y/interactive-supports-focus
|
||||
<div {...props} onKeyDown={onKeyDownHandler} role="toolbar" ref={ref}>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -104,7 +104,6 @@ export default class CommandProvider extends AutocompleteProvider {
|
||||
return (
|
||||
<div
|
||||
className="mx_Autocomplete_Completion_container_pill"
|
||||
role="presentation"
|
||||
aria-label={_t("composer|autocomplete|command_a11y")}
|
||||
>
|
||||
{completions}
|
||||
|
||||
@@ -175,7 +175,6 @@ export default class EmojiProvider extends AutocompleteProvider {
|
||||
return (
|
||||
<div
|
||||
className="mx_Autocomplete_Completion_container_pill"
|
||||
role="presentation"
|
||||
aria-label={_t("composer|autocomplete|emoji_a11y")}
|
||||
>
|
||||
{completions}
|
||||
|
||||
@@ -68,7 +68,6 @@ export default class NotifProvider extends AutocompleteProvider {
|
||||
return (
|
||||
<div
|
||||
className="mx_Autocomplete_Completion_container_pill mx_Autocomplete_Completion_container_truncate"
|
||||
role="presentation"
|
||||
aria-label={_t("composer|autocomplete|notification_a11y")}
|
||||
>
|
||||
{completions}
|
||||
|
||||
@@ -136,7 +136,6 @@ export default class RoomProvider extends AutocompleteProvider {
|
||||
return (
|
||||
<div
|
||||
className="mx_Autocomplete_Completion_container_pill mx_Autocomplete_Completion_container_truncate"
|
||||
role="presentation"
|
||||
aria-label={_t("composer|autocomplete|room_a11y")}
|
||||
>
|
||||
{completions}
|
||||
|
||||
@@ -196,7 +196,6 @@ export default class UserProvider extends AutocompleteProvider {
|
||||
return (
|
||||
<div
|
||||
className="mx_Autocomplete_Completion_container_pill"
|
||||
role="presentation"
|
||||
aria-label={_t("composer|autocomplete|user_a11y")}
|
||||
>
|
||||
{completions}
|
||||
|
||||
@@ -115,6 +115,8 @@ export const AutocompleteInput: React.FC<AutocompleteInputProps> = ({
|
||||
|
||||
return (
|
||||
<div className="mx_AutocompleteInput">
|
||||
{/* We break the rule here as this is a mouse-only interaction */}
|
||||
{/* oxlint-disable-next-line jsx-a11y/click-events-have-key-events */}
|
||||
<div
|
||||
ref={editorContainerRef}
|
||||
className={classNames({
|
||||
|
||||
@@ -402,6 +402,8 @@ export default class ContextMenu extends React.PureComponent<React.PropsWithChil
|
||||
let background: JSX.Element;
|
||||
if (hasBackground) {
|
||||
background = (
|
||||
// We break the rule here as this is a mouse-only interaction
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div
|
||||
className="mx_ContextualMenu_background"
|
||||
style={wrapperStyle}
|
||||
|
||||
@@ -180,7 +180,6 @@ const Tile: React.FC<ITileProps> = ({
|
||||
if (hasPermissions) {
|
||||
checkbox = (
|
||||
<StyledCheckbox
|
||||
role="presentation"
|
||||
aria-labelledby={checkboxLabelId}
|
||||
checked={!!selected}
|
||||
tabIndex={-1}
|
||||
@@ -198,12 +197,7 @@ const Tile: React.FC<ITileProps> = ({
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<StyledCheckbox
|
||||
role="presentation"
|
||||
aria-labelledby={checkboxLabelId}
|
||||
disabled={true}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
<StyledCheckbox aria-labelledby={checkboxLabelId} disabled={true} tabIndex={-1} />
|
||||
</TextWithTooltip>
|
||||
);
|
||||
}
|
||||
@@ -287,8 +281,9 @@ const Tile: React.FC<ITileProps> = ({
|
||||
let childSection: JSX.Element | undefined;
|
||||
let onKeyDown: KeyboardEventHandler | undefined;
|
||||
if (children) {
|
||||
// the chevron is purposefully a div rather than a button as it should be ignored for a11y
|
||||
childToggle = (
|
||||
// the chevron is purposefully a div rather than a button as it should be ignored for a11y
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div
|
||||
className={classNames("mx_SpaceHierarchy_subspace_toggle", {
|
||||
mx_SpaceHierarchy_subspace_toggle_shown: showChildren,
|
||||
|
||||
@@ -102,6 +102,8 @@ function TabLabel<T extends string>({ tab, isActive, showToolip, onClick }: ITab
|
||||
|
||||
const label = _t(tab.label);
|
||||
return (
|
||||
// The RovingAccessibleComponent correctly sets the tabIndex based on roving context
|
||||
// oxlint-disable-next-line jsx-a11y/interactive-supports-focus
|
||||
<RovingAccessibleButton
|
||||
className={classes}
|
||||
onClick={onClick}
|
||||
|
||||
@@ -58,6 +58,7 @@ const BeaconListItem: React.FC<Props & HTMLProps<HTMLLIElement>> = ({ beacon, ..
|
||||
>
|
||||
{/* eat events from interactive share buttons
|
||||
so parent click handlers are not triggered */}
|
||||
{/* oxlint-disable-next-line jsx-a11y/click-events-have-key-events */}
|
||||
<div className="mx_BeaconListItem_interactions" onClick={preventDefaultWrapper(() => {})}>
|
||||
<ShareLatestLocation latestLocationState={latestLocationState} />
|
||||
</div>
|
||||
|
||||
@@ -54,6 +54,9 @@ class MenuOption extends React.Component<IMenuOptionProps> {
|
||||
});
|
||||
|
||||
return (
|
||||
// We break the rule here as this is a mouse-only interaction,
|
||||
// the keyboard interaction is handled by the Dropdown parent component
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<li
|
||||
id={this.props.id}
|
||||
className={optClasses}
|
||||
|
||||
@@ -79,7 +79,6 @@ export class EditableItem extends React.Component<IItemProps, IItemState> {
|
||||
onClick={this.onRemove}
|
||||
className="mx_EditableItem_delete"
|
||||
title={_t("action|remove")}
|
||||
role="button"
|
||||
>
|
||||
<CloseIcon />
|
||||
</AccessibleButton>
|
||||
|
||||
@@ -201,6 +201,8 @@ export default class EditableText extends React.Component<IProps, IState> {
|
||||
if (!editable || (this.state.phase === Phases.Display && (label || labelClassName) && !this.value)) {
|
||||
// show the label
|
||||
editableEl = (
|
||||
// We break the rule here as this is a mouse-only shortcut
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div className={className + " " + labelClassName} onClick={this.onClickDiv}>
|
||||
{label || initialValue}
|
||||
</div>
|
||||
|
||||
@@ -99,6 +99,9 @@ const GenericEventListSummary: React.FC<IProps> = ({
|
||||
body = (
|
||||
<div className="mx_EventTile_line">
|
||||
<div className="mx_EventTile_info">
|
||||
{/* We break the rule here as this is a mouse-only interaction */}
|
||||
{/* mx_GenericEventListSummary_toggle is the keyboard friendly outer one */}
|
||||
{/* oxlint-disable-next-line jsx-a11y/click-events-have-key-events */}
|
||||
<span className="mx_GenericEventListSummary_avatars" onClick={toggleExpanded}>
|
||||
{avatars}
|
||||
</span>
|
||||
|
||||
@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { type JSX, useCallback, useContext, useState } from "react";
|
||||
import { type Room, EventType } from "matrix-js-sdk/src/matrix";
|
||||
import classNames from "classnames";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
import { LinkedText } from "@element-hq/web-shared-components";
|
||||
|
||||
import { useTopic } from "../../../hooks/room/useTopic";
|
||||
@@ -20,15 +19,16 @@ import Modal from "../../../Modal";
|
||||
import InfoDialog from "../dialogs/InfoDialog";
|
||||
import { useDispatcher } from "../../../hooks/useDispatcher";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
import AccessibleButton, { type ButtonEvent } from "./AccessibleButton";
|
||||
import { topicToHtml } from "../../../HtmlUtils";
|
||||
import { tryTransformPermalinkToLocalHref } from "../../../utils/permalinks/Permalinks";
|
||||
|
||||
interface IProps extends React.HTMLProps<HTMLDivElement> {
|
||||
interface IProps {
|
||||
room: Room;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function onRoomTopicLinkClick(e: React.MouseEvent): void {
|
||||
export function onRoomTopicLinkClick(e: ButtonEvent): void {
|
||||
const anchor = e.target as HTMLLinkElement;
|
||||
const localHref = tryTransformPermalinkToLocalHref(anchor.href);
|
||||
|
||||
@@ -39,28 +39,23 @@ export function onRoomTopicLinkClick(e: React.MouseEvent): void {
|
||||
}
|
||||
}
|
||||
|
||||
export default function RoomTopic({ room, className, ...props }: IProps): JSX.Element {
|
||||
export default function RoomTopic({ room, className }: IProps): JSX.Element {
|
||||
const client = useContext(MatrixClientContext);
|
||||
const [disableTooltip, setDisableTooltip] = useState(false);
|
||||
|
||||
const topic = useTopic(room);
|
||||
const body = topicToHtml(topic?.text, topic?.html);
|
||||
|
||||
const onClick = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
props.onClick?.(e);
|
||||
const onClick = useCallback((e: ButtonEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.tagName.toUpperCase() !== "A") {
|
||||
dis.fire(Action.ShowRoomTopic);
|
||||
return;
|
||||
}
|
||||
|
||||
if (target.tagName.toUpperCase() !== "A") {
|
||||
dis.fire(Action.ShowRoomTopic);
|
||||
return;
|
||||
}
|
||||
|
||||
onRoomTopicLinkClick(e);
|
||||
},
|
||||
[props],
|
||||
);
|
||||
onRoomTopicLinkClick(e);
|
||||
}, []);
|
||||
|
||||
const onHover = (ev: React.MouseEvent | React.FocusEvent): void => {
|
||||
setDisableTooltip((ev.target as HTMLElement).tagName.toUpperCase() === "A");
|
||||
@@ -100,19 +95,15 @@ export default function RoomTopic({ room, className, ...props }: IProps): JSX.El
|
||||
if (!body) return <div className={classNames(className, "mx_RoomTopic")} />;
|
||||
|
||||
return (
|
||||
<Tooltip description={_t("room|read_topic")} disabled={disableTooltip}>
|
||||
<div
|
||||
{...props}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onClick={onClick}
|
||||
className={classNames(className, "mx_RoomTopic")}
|
||||
onMouseOver={onHover}
|
||||
onFocus={onHover}
|
||||
aria-label={_t("room|read_topic")}
|
||||
>
|
||||
<LinkedText>{body}</LinkedText>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<AccessibleButton
|
||||
onClick={onClick}
|
||||
className={classNames(className, "mx_RoomTopic")}
|
||||
onMouseOver={onHover}
|
||||
onFocus={onHover}
|
||||
title={_t("room|read_topic")}
|
||||
disableTooltip={disableTooltip}
|
||||
>
|
||||
<LinkedText>{body}</LinkedText>
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ export default ({ checked, disabled = false, onChange, title, tooltip, ...props
|
||||
className={classes}
|
||||
onClick={_onClick}
|
||||
role="switch"
|
||||
tabIndex={0}
|
||||
aria-label={title}
|
||||
aria-checked={checked}
|
||||
aria-disabled={disabled}
|
||||
|
||||
@@ -174,6 +174,8 @@ const MapComponent: React.FC<MapProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
// We break the rule here as this is a mouse-only interaction
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div className={classNames("mx_Map", className)} id={bodyId} onClick={onMapClick}>
|
||||
{!!children && !!map && children({ map })}
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,8 @@ export interface MapErrorProps {
|
||||
}
|
||||
|
||||
export const MapError: React.FC<MapErrorProps> = ({ error, isMinimised, className, onFinished, onClick }) => (
|
||||
// We break the rule here as this is a mouse-only interaction
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div
|
||||
data-testid="map-rendering-error"
|
||||
className={classNames("mx_MapError", className, { mx_MapError_isMinimised: isMinimised })}
|
||||
|
||||
@@ -46,6 +46,8 @@ const OptionalTooltip: React.FC<{
|
||||
};
|
||||
|
||||
return (
|
||||
// We break the rule here as this is a mouse-only interaction
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div onMouseEnter={show} onClick={toggleVisibility} onMouseLeave={hide}>
|
||||
{children}
|
||||
{isVisible && tooltip}
|
||||
|
||||
@@ -13,6 +13,8 @@ import { CollapseIcon, CopyIcon, ExpandIcon } from "@vector-im/compound-design-t
|
||||
|
||||
import { useSettingValue } from "../../../hooks/useSettings.ts";
|
||||
import { CopyTextButton } from "../elements/CopyableText.tsx";
|
||||
import AccessibleButton from "../elements/AccessibleButton.tsx";
|
||||
import { _t } from "../../../i18n";
|
||||
|
||||
const MAX_HIGHLIGHT_LENGTH = 4096;
|
||||
const MAX_LINES_BEFORE_COLLAPSE = 5;
|
||||
@@ -26,9 +28,14 @@ const ExpandCollapseButton: React.FC<{
|
||||
onClick(this: void): void;
|
||||
}> = ({ expanded, onClick }) => {
|
||||
return (
|
||||
<span className="mx_EventTile_button" onClick={onClick}>
|
||||
<AccessibleButton
|
||||
element="button"
|
||||
title={expanded ? _t("action|collapse") : _t("action|expand")}
|
||||
onClick={onClick}
|
||||
className="mx_EventTile_button"
|
||||
>
|
||||
{expanded ? <CollapseIcon /> : <ExpandIcon />}
|
||||
</span>
|
||||
</AccessibleButton>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,10 +14,11 @@ import { BLURHASH_FIELD } from "../../../utils/image-media";
|
||||
import IconsShowStickersSvg from "../../../../res/img/icons-show-stickers.svg";
|
||||
import { type IBodyProps } from "./IBodyProps";
|
||||
import { useMediaVisible } from "../../../hooks/useMediaVisible";
|
||||
import AccessibleButton, { type ButtonEvent } from "../elements/AccessibleButton.tsx";
|
||||
|
||||
class MStickerBodyInner extends ImageBodyBaseInner {
|
||||
// Mostly empty to prevent default behaviour of MImageBody
|
||||
protected onClick = (ev: React.MouseEvent): void => {
|
||||
protected onClick = (ev: ButtonEvent): void => {
|
||||
ev.preventDefault();
|
||||
if (!this.props.mediaVisible) {
|
||||
this.props.setMediaVisible(true);
|
||||
@@ -27,16 +28,15 @@ class MStickerBodyInner extends ImageBodyBaseInner {
|
||||
// MStickerBody doesn't need a wrapping `<a href=...>`, but it does need extra padding
|
||||
// which is added by mx_MStickerBody_wrapper
|
||||
protected wrapImage(contentUrl: string, children: React.ReactNode): JSX.Element {
|
||||
let onClick: React.MouseEventHandler | undefined;
|
||||
if (!this.props.mediaVisible) {
|
||||
onClick = this.onClick;
|
||||
const content = <> {children} </>;
|
||||
if (this.props.mediaVisible) {
|
||||
return (
|
||||
<AccessibleButton className="mx_MStickerBody_wrapper" onClick={this.onClick}>
|
||||
{content}
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="mx_MStickerBody_wrapper" onClick={onClick}>
|
||||
{" "}
|
||||
{children}{" "}
|
||||
</div>
|
||||
);
|
||||
return <div className="mx_MStickerBody_wrapper">{content}</div>;
|
||||
}
|
||||
|
||||
// Placeholder to show in place of the sticker image if img onLoad hasn't fired yet.
|
||||
|
||||
@@ -112,6 +112,8 @@ export const PollOption: React.FC<PollOptionProps> = ({
|
||||
const isWinner = isEnded && isChecked;
|
||||
const answerPercent = totalVoteCount === 0 ? 0 : Math.round((100.0 * voteCount) / totalVoteCount);
|
||||
return (
|
||||
// We break the rule here as ActivePollOption is keyboard accessible, we are just making the click target larger
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div data-testid={`pollOption-${answer.id}`} className={cls} onClick={() => onOptionSelected?.(answer.id)}>
|
||||
<ActivePollOption
|
||||
pollId={pollId}
|
||||
|
||||
@@ -9,11 +9,11 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { type PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
|
||||
import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
import { PollsIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { formatLocalDateShort } from "../../../../DateUtils";
|
||||
import { _t } from "../../../../languageHandler";
|
||||
import AccessibleButton from "../../elements/AccessibleButton.tsx";
|
||||
|
||||
interface Props {
|
||||
event: MatrixEvent;
|
||||
@@ -27,14 +27,19 @@ export const PollListItem: React.FC<Props> = ({ event, onClick }) => {
|
||||
}
|
||||
const formattedDate = formatLocalDateShort(event.getTs());
|
||||
return (
|
||||
<li data-testid={`pollListItem-${event.getId()!}`} className="mx_PollListItem" onClick={onClick}>
|
||||
<Tooltip label={_t("right_panel|poll|view_poll")} placement="top" isTriggerInteractive={false}>
|
||||
<li data-testid={`pollListItem-${event.getId()!}`} className="mx_PollListItem">
|
||||
<AccessibleButton
|
||||
className="mx_PollListItemEnded_content"
|
||||
title={_t("right_panel|poll|view_poll")}
|
||||
placement="top"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="mx_PollListItem_content">
|
||||
<span>{formattedDate}</span>
|
||||
<PollsIcon className="mx_PollListItem_icon" />
|
||||
<span className="mx_PollListItem_question">{pollEvent.question.text}</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</AccessibleButton>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { type PollAnswerSubevent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
|
||||
import { type MatrixEvent, type Poll, PollEvent, type Relations } from "matrix-js-sdk/src/matrix";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
import { PollsEndIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { _t } from "../../../../languageHandler";
|
||||
@@ -17,6 +16,7 @@ import { formatLocalDateShort } from "../../../../DateUtils";
|
||||
import { allVotes, collectUserVotes, countVotes } from "../../messages/MPollBody";
|
||||
import { PollOption } from "../../polls/PollOption";
|
||||
import { Caption } from "../../typography/Caption";
|
||||
import AccessibleButton from "../../elements/AccessibleButton.tsx";
|
||||
|
||||
interface Props {
|
||||
event: MatrixEvent;
|
||||
@@ -93,36 +93,39 @@ export const PollListItemEnded: React.FC<Props> = ({ event, poll, onClick }) =>
|
||||
const formattedDate = formatLocalDateShort(event.getTs());
|
||||
|
||||
return (
|
||||
<li data-testid={`pollListItem-${event.getId()!}`} className="mx_PollListItemEnded" onClick={onClick}>
|
||||
<Tooltip label={_t("right_panel|poll|view_poll")} placement="top" isTriggerInteractive={false}>
|
||||
<div className="mx_PollListItemEnded_content">
|
||||
<div className="mx_PollListItemEnded_title">
|
||||
<PollsEndIcon className="mx_PollListItemEnded_icon" />
|
||||
<span className="mx_PollListItemEnded_question">{pollEvent.question.text}</span>
|
||||
<Caption>{formattedDate}</Caption>
|
||||
</div>
|
||||
{!!winningAnswers?.length && (
|
||||
<div className="mx_PollListItemEnded_answers">
|
||||
{winningAnswers?.map(({ answer, voteCount, optionNumber }) => (
|
||||
<PollOption
|
||||
key={answer.id}
|
||||
answer={answer}
|
||||
voteCount={voteCount}
|
||||
totalVoteCount={totalVoteCount!}
|
||||
pollId={poll.pollId}
|
||||
optionNumber={optionNumber}
|
||||
displayVoteCount
|
||||
isChecked
|
||||
isEnded
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="mx_PollListItemEnded_voteCount">
|
||||
<Caption>{_t("right_panel|poll|final_result", { count: totalVoteCount })}</Caption>
|
||||
</div>
|
||||
<li data-testid={`pollListItem-${event.getId()!}`} className="mx_PollListItemEnded">
|
||||
<AccessibleButton
|
||||
className="mx_PollListItemEnded_content"
|
||||
title={_t("right_panel|poll|view_poll")}
|
||||
placement="top"
|
||||
onClick={onClick}
|
||||
>
|
||||
<div className="mx_PollListItemEnded_title">
|
||||
<PollsEndIcon className="mx_PollListItemEnded_icon" />
|
||||
<span className="mx_PollListItemEnded_question">{pollEvent.question.text}</span>
|
||||
<Caption>{formattedDate}</Caption>
|
||||
</div>
|
||||
</Tooltip>
|
||||
{!!winningAnswers?.length && (
|
||||
<div className="mx_PollListItemEnded_answers">
|
||||
{winningAnswers?.map(({ answer, voteCount, optionNumber }) => (
|
||||
<PollOption
|
||||
key={answer.id}
|
||||
answer={answer}
|
||||
voteCount={voteCount}
|
||||
totalVoteCount={totalVoteCount!}
|
||||
pollId={poll.pollId}
|
||||
optionNumber={optionNumber}
|
||||
displayVoteCount
|
||||
isChecked
|
||||
isEnded
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div className="mx_PollListItemEnded_voteCount">
|
||||
<Caption>{_t("right_panel|poll|final_result", { count: totalVoteCount })}</Caption>
|
||||
</div>
|
||||
</AccessibleButton>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -128,6 +128,7 @@ const BaseCard: React.FC<IProps> = ({
|
||||
weight="medium"
|
||||
className="mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
aria-level={1}
|
||||
>
|
||||
{header}
|
||||
</Text>
|
||||
|
||||
@@ -857,6 +857,8 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
|
||||
aria-multiline="true"
|
||||
aria-autocomplete="list"
|
||||
aria-haspopup="listbox"
|
||||
// This is not strictly speaking a supported role, we should investigate the impact of this in the future
|
||||
// oxlint-disable-next-line jsx-a11y/role-supports-aria-props
|
||||
aria-expanded={hasAutocomplete ? !this.autocompleteRef.current?.state.hide : undefined}
|
||||
aria-owns={hasAutocomplete ? "mx_Autocomplete" : undefined}
|
||||
aria-activedescendant={activeDescendant}
|
||||
|
||||
@@ -46,6 +46,7 @@ export function MemberTileView(props: Props): JSX.Element {
|
||||
aria-label={props?.ariaLabel}
|
||||
tabIndex={props.tabIndex}
|
||||
role="option"
|
||||
aria-selected={props.tabIndex === 0}
|
||||
aria-posinset={props.memberIndex + 1}
|
||||
aria-setsize={props.memberCount}
|
||||
>
|
||||
|
||||
@@ -114,7 +114,7 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
|
||||
if (this.state.canKick && this.state.invited) {
|
||||
adminTools = (
|
||||
<Flex direction="column" as="section" justify="start" gap="var(--cpd-space-2x)">
|
||||
<Text as="span" role="heading" size="lg" weight="semibold">
|
||||
<Text as="span" role="heading" size="lg" weight="semibold" aria-level={3}>
|
||||
{_t("user_info|admin_tools_section")}
|
||||
</Text>
|
||||
<Button size="md" kind="destructive" className="mx_MemberInfo_field" onClick={this.onKickClick}>
|
||||
@@ -129,7 +129,7 @@ export default class ThirdPartyMemberInfo extends React.Component<IProps, IState
|
||||
<Flex className="mx_ThirdPartyMemberInfo" direction="column" gap="var(--cpd-space-4x)">
|
||||
<Flex direction="column" as="section" justify="start" gap="var(--cpd-space-2x)">
|
||||
{/* same as userinfo name style */}
|
||||
<Text as="span" role="heading" size="lg" weight="semibold">
|
||||
<Text as="span" role="heading" size="lg" weight="semibold" aria-level={2}>
|
||||
{this.state.displayName}
|
||||
</Text>
|
||||
<Text as="span">{_t("user_info|invited_by", { sender: this.state.senderName })}</Text>
|
||||
|
||||
@@ -50,7 +50,7 @@ const DeviceNameEditor: React.FC<Props & { stopEditing: () => void }> = ({ devic
|
||||
const descriptionId = `device-rename-description-${device.device_id}`;
|
||||
|
||||
return (
|
||||
<form aria-disabled={isLoading} className="mx_DeviceDetailHeading_renameForm" onSubmit={onSubmit} method="post">
|
||||
<form className="mx_DeviceDetailHeading_renameForm" onSubmit={onSubmit} method="post">
|
||||
<p id={headingId} className="mx_DeviceDetailHeading_renameFormHeading">
|
||||
{_t("settings|sessions|rename_form_heading")}
|
||||
</p>
|
||||
|
||||
@@ -31,6 +31,8 @@ const DeviceTileName: React.FC<{ device: ExtendedDevice }> = ({ device }) => {
|
||||
|
||||
const DeviceTile: React.FC<DeviceTileProps> = ({ device, children, isSelected, onClick }) => {
|
||||
return (
|
||||
// We break the rule here as this is a mouse-only shortcut
|
||||
// oxlint-disable-next-line jsx-a11y/click-events-have-key-events
|
||||
<div
|
||||
className={classNames("mx_DeviceTile", { mx_DeviceTile_interactive: !!onClick })}
|
||||
data-testid={`device-tile-${device.device_id}`}
|
||||
@@ -43,6 +45,8 @@ const DeviceTile: React.FC<DeviceTileProps> = ({ device, children, isSelected, o
|
||||
<DeviceMetaData device={device} />
|
||||
</div>
|
||||
</div>
|
||||
{/* We break the rule here as this is a mouse-only interaction */}
|
||||
{/* oxlint-disable-next-line jsx-a11y/click-events-have-key-events */}
|
||||
<div className="mx_DeviceTile_actions" onClick={preventDefaultWrapper(() => {})}>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ exports[`FilePanel renders empty state 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
@@ -3628,6 +3628,7 @@ exports[`RoomView video rooms should render joined video room view 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
-8
@@ -137,7 +137,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
|
||||
aria-labelledby="react-use-id-1"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_MwbPDmfGtm"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -235,7 +234,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
|
||||
aria-labelledby="react-use-id-2"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_GQvdMWe954"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -334,7 +332,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
|
||||
aria-labelledby="react-use-id-3"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_DVIAu5CsiH"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -455,7 +452,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
|
||||
class="_input_153f2_18"
|
||||
disabled=""
|
||||
id="checkbox_RD7nyrA2oh"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -556,7 +552,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> renders 1`] = `
|
||||
aria-labelledby="react-use-id-6"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_jWVJIPauy1"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -727,7 +722,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> should not render cycles 1`] = `
|
||||
aria-labelledby="react-use-id-1"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_EetmBG4yVC"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -825,7 +819,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> should not render cycles 1`] = `
|
||||
aria-labelledby="react-use-id-2"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_eEefiPqpMR"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
@@ -924,7 +917,6 @@ exports[`SpaceHierarchy <SpaceHierarchy /> should not render cycles 1`] = `
|
||||
aria-labelledby="react-use-id-3"
|
||||
class="_input_153f2_18"
|
||||
id="checkbox_MwbPDmfGtm"
|
||||
role="presentation"
|
||||
tabindex="-1"
|
||||
type="checkbox"
|
||||
/>
|
||||
|
||||
+6
-3
@@ -467,8 +467,11 @@ num_sqrt = num **
|
||||
</code>
|
||||
</div>
|
||||
</pre>
|
||||
<span
|
||||
class="mx_EventTile_button"
|
||||
<button
|
||||
aria-label="Expand"
|
||||
class="mx_AccessibleButton mx_EventTile_button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
fill="currentColor"
|
||||
@@ -481,7 +484,7 @@ num_sqrt = num **
|
||||
d="M21 3.997a1 1 0 0 0-.29-.702l-.005-.004A1 1 0 0 0 20 3h-8a1 1 0 1 0 0 2h5.586L5 17.586V12a1 1 0 1 0-2 0v8.003a1 1 0 0 0 .29.702l.005.004c.18.18.43.291.705.291h8a1 1 0 1 0 0-2H6.414L19 6.414V12a1 1 0 1 0 2 0z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
aria-label="Copy"
|
||||
class="mx_AccessibleButton mx_EventTile_button mx_EventTile_copyButton mx_EventTile_buttonBottom"
|
||||
|
||||
+10
-6
@@ -114,11 +114,13 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
|
||||
class="mx_PollListItem"
|
||||
data-testid="pollListItem-$2"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
aria-label="View poll"
|
||||
class="mx_AccessibleButton mx_PollListItemEnded_content"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="react-use-id-1"
|
||||
class="mx_PollListItem_content"
|
||||
>
|
||||
<span>
|
||||
@@ -142,17 +144,19 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
|
||||
Where?
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li
|
||||
class="mx_PollListItem"
|
||||
data-testid="pollListItem-$1"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
aria-label="View poll"
|
||||
class="mx_AccessibleButton mx_PollListItemEnded_content"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="react-use-id-2"
|
||||
class="mx_PollListItem_content"
|
||||
>
|
||||
<span>
|
||||
@@ -176,7 +180,7 @@ exports[`<PollHistory /> renders a list of active polls when there are polls in
|
||||
Question?
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
+5
-3
@@ -6,11 +6,13 @@ exports[`<PollListItem /> renders a poll 1`] = `
|
||||
class="mx_PollListItem"
|
||||
data-testid="pollListItem-$mypoll"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
aria-label="View poll"
|
||||
class="mx_AccessibleButton mx_PollListItemEnded_content"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="react-use-id-1"
|
||||
class="mx_PollListItem_content"
|
||||
>
|
||||
<span>
|
||||
@@ -34,7 +36,7 @@ exports[`<PollListItem /> renders a poll 1`] = `
|
||||
Question?
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
`;
|
||||
|
||||
+38
-40
@@ -6,53 +6,51 @@ exports[`<PollListItemEnded /> renders a poll with no responses 1`] = `
|
||||
class="mx_PollListItemEnded"
|
||||
data-testid="pollListItem-1"
|
||||
>
|
||||
<span
|
||||
<div
|
||||
aria-label="View poll"
|
||||
class="mx_AccessibleButton mx_PollListItemEnded_content"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
aria-labelledby="react-use-id-1"
|
||||
class="mx_PollListItemEnded_content"
|
||||
class="mx_PollListItemEnded_title"
|
||||
>
|
||||
<div
|
||||
class="mx_PollListItemEnded_title"
|
||||
<svg
|
||||
class="mx_PollListItemEnded_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg
|
||||
class="mx_PollListItemEnded_icon"
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M21 10.659V19q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21H5q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h8.341A6 6 0 0 0 13 5H5v14h14v-8a6 6 0 0 0 2-.341"
|
||||
/>
|
||||
<path
|
||||
d="M13.803 8a6 6 0 0 0 1.88 2H13a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 9q0-.424.287-.713A.97.97 0 0 1 13 8zm2.91 7.713A.97.97 0 0 1 16 16h-3a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 15q0-.424.287-.713A.97.97 0 0 1 13 14h3q.424 0 .712.287.288.288.288.713 0 .424-.288.713m-6.299-5.3A1.93 1.93 0 0 1 9 11q-.825 0-1.412-.588A1.93 1.93 0 0 1 7 9q0-.825.588-1.412A1.93 1.93 0 0 1 9 7q.825 0 1.412.588Q11 8.175 11 9t-.588 1.412m.001 6.001A1.93 1.93 0 0 1 9 17q-.825 0-1.412-.587A1.93 1.93 0 0 1 7 15q0-.825.588-1.412A1.93 1.93 0 0 1 9 13q.825 0 1.412.588Q11 14.175 11 15q0 .824-.588 1.413m12.295-14.12a1 1 0 0 1 0 1.414l-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L18 5.586l3.293-3.293a1 1 0 0 1 1.414 0"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PollListItemEnded_question"
|
||||
>
|
||||
Question?
|
||||
</span>
|
||||
<span
|
||||
class="mx_Caption"
|
||||
>
|
||||
02/02/23
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mx_PollListItemEnded_voteCount"
|
||||
<path
|
||||
d="M21 10.659V19q0 .824-.587 1.413A1.93 1.93 0 0 1 19 21H5q-.824 0-1.412-.587A1.93 1.93 0 0 1 3 19V5q0-.824.587-1.412A1.93 1.93 0 0 1 5 3h8.341A6 6 0 0 0 13 5H5v14h14v-8a6 6 0 0 0 2-.341"
|
||||
/>
|
||||
<path
|
||||
d="M13.803 8a6 6 0 0 0 1.88 2H13a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 9q0-.424.287-.713A.97.97 0 0 1 13 8zm2.91 7.713A.97.97 0 0 1 16 16h-3a.97.97 0 0 1-.713-.287A.97.97 0 0 1 12 15q0-.424.287-.713A.97.97 0 0 1 13 14h3q.424 0 .712.287.288.288.288.713 0 .424-.288.713m-6.299-5.3A1.93 1.93 0 0 1 9 11q-.825 0-1.412-.588A1.93 1.93 0 0 1 7 9q0-.825.588-1.412A1.93 1.93 0 0 1 9 7q.825 0 1.412.588Q11 8.175 11 9t-.588 1.412m.001 6.001A1.93 1.93 0 0 1 9 17q-.825 0-1.412-.587A1.93 1.93 0 0 1 7 15q0-.825.588-1.412A1.93 1.93 0 0 1 9 13q.825 0 1.412.588Q11 14.175 11 15q0 .824-.588 1.413m12.295-14.12a1 1 0 0 1 0 1.414l-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L18 5.586l3.293-3.293a1 1 0 0 1 1.414 0"
|
||||
/>
|
||||
</svg>
|
||||
<span
|
||||
class="mx_PollListItemEnded_question"
|
||||
>
|
||||
<span
|
||||
class="mx_Caption"
|
||||
>
|
||||
Final result based on 0 votes
|
||||
</span>
|
||||
</div>
|
||||
Question?
|
||||
</span>
|
||||
<span
|
||||
class="mx_Caption"
|
||||
>
|
||||
02/02/23
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<div
|
||||
class="mx_PollListItemEnded_voteCount"
|
||||
>
|
||||
<span
|
||||
class="mx_Caption"
|
||||
>
|
||||
Final result based on 0 votes
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
`;
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ exports[`<BaseCard /> should close when clicking X button 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ exports[`<ExtensionsCard /> should render empty state 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
@@ -113,6 +114,7 @@ exports[`<ExtensionsCard /> should render widgets 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
+3
@@ -12,6 +12,7 @@ exports[`<PinnedMessagesCard /> should show the empty state when there are no pi
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
@@ -94,6 +95,7 @@ exports[`<PinnedMessagesCard /> should show two pinned messages 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
@@ -322,6 +324,7 @@ exports[`<PinnedMessagesCard /> unpin all should not allow to unpinall 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ exports[`<UserInfo /> with crypto enabled renders <BasicUserInfo /> 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
@@ -314,6 +315,7 @@ exports[`<UserInfo /> with crypto enabled should render a deactivate button for
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
+4
@@ -12,6 +12,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite 1`] = `
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
@@ -58,6 +59,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite 1`] = `
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<span
|
||||
aria-level="2"
|
||||
class="_typography_6v6n8_153 _font-body-lg-semibold_6v6n8_74"
|
||||
role="heading"
|
||||
>
|
||||
@@ -87,6 +89,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite when room in not availabl
|
||||
class="mx_BaseCard_header_title"
|
||||
>
|
||||
<p
|
||||
aria-level="1"
|
||||
class="_typography_6v6n8_153 _font-body-md-medium_6v6n8_60 mx_BaseCard_header_title_heading"
|
||||
role="heading"
|
||||
>
|
||||
@@ -133,6 +136,7 @@ exports[`<ThirdPartyMemberInfo /> should render invite when room in not availabl
|
||||
style="--mx-flex-display: flex; --mx-flex-direction: column; --mx-flex-align: start; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-2x); --mx-flex-wrap: nowrap;"
|
||||
>
|
||||
<span
|
||||
aria-level="2"
|
||||
class="_typography_6v6n8_153 _font-body-lg-semibold_6v6n8_74"
|
||||
role="heading"
|
||||
>
|
||||
|
||||
+4
@@ -6,6 +6,7 @@ exports[`MemberTileView RoomMemberTileView should display an verified E2EIcon wh
|
||||
<div
|
||||
aria-label="@userId:matrix.org"
|
||||
aria-posinset="1"
|
||||
aria-selected="false"
|
||||
aria-setsize="1"
|
||||
class="mx_AccessibleButton mx_MemberTileView"
|
||||
role="option"
|
||||
@@ -84,6 +85,7 @@ exports[`MemberTileView RoomMemberTileView should display an warning E2EIcon whe
|
||||
<div
|
||||
aria-label="@userId:matrix.org"
|
||||
aria-posinset="1"
|
||||
aria-selected="false"
|
||||
aria-setsize="1"
|
||||
class="mx_AccessibleButton mx_MemberTileView"
|
||||
role="option"
|
||||
@@ -162,6 +164,7 @@ exports[`MemberTileView RoomMemberTileView should not display an E2EIcon when th
|
||||
<div
|
||||
aria-label="@userId:matrix.org"
|
||||
aria-posinset="1"
|
||||
aria-selected="false"
|
||||
aria-setsize="1"
|
||||
class="mx_AccessibleButton mx_MemberTileView"
|
||||
role="option"
|
||||
@@ -222,6 +225,7 @@ exports[`MemberTileView ThreePidInviteTileView renders ThreePidInvite correctly
|
||||
<div
|
||||
aria-label="Foobar"
|
||||
aria-posinset="1"
|
||||
aria-selected="false"
|
||||
aria-setsize="1"
|
||||
class="mx_AccessibleButton mx_MemberTileView"
|
||||
role="option"
|
||||
|
||||
-1
@@ -4,7 +4,6 @@ exports[`<DeviceDetailHeading /> displays name edit form on rename button click
|
||||
{
|
||||
"container": <div>
|
||||
<form
|
||||
aria-disabled="false"
|
||||
class="mx_DeviceDetailHeading_renameForm"
|
||||
method="post"
|
||||
>
|
||||
|
||||
+6
-6
@@ -163,18 +163,14 @@ export default defineConfig({
|
||||
"react-perf/jsx-no-new-array-as-prop": "off",
|
||||
"react/no-did-update-set-state": "off",
|
||||
"react/no-did-mount-set-state": "off",
|
||||
"jsx-a11y/interactive-supports-focus": "off",
|
||||
"jsx-a11y/no-static-element-interactions": "off",
|
||||
"jsx-a11y/click-events-have-key-events": "off",
|
||||
"vitest/no-conditional-tests": "off",
|
||||
"jsx-a11y/no-noninteractive-element-interactions": "off",
|
||||
"react/no-array-index-key": "off",
|
||||
"jsx-a11y/control-has-associated-label": "off",
|
||||
"jsx-a11y/role-supports-aria-props": "off",
|
||||
"jsx-a11y/media-has-caption": "off",
|
||||
"jsx-a11y/no-noninteractive-element-to-interactive-role": "off",
|
||||
"jsx-a11y/aria-activedescendant-has-tabindex": "off",
|
||||
"jsx-a11y/role-has-required-aria-props": "off",
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
@@ -417,13 +413,17 @@ export default defineConfig({
|
||||
],
|
||||
"jsdoc/check-tag-names": "off",
|
||||
|
||||
"react/jsx-no-constructed-context-values": "off",
|
||||
// Disable a11y rules for components in tests
|
||||
"jsx-a11y/role-has-required-aria-props": "off",
|
||||
"jsx-a11y/interactive-supports-focus": "off",
|
||||
"jsx-a11y/no-static-element-interactions": "off",
|
||||
"react/no-array-index-key": "off",
|
||||
"jsx-a11y/click-events-have-key-events": "off",
|
||||
"jsx-a11y/media-has-caption": "off",
|
||||
"jsx-a11y/no-noninteractive-element-to-interactive-role": "off",
|
||||
"jsx-a11y/role-supports-aria-props": "off",
|
||||
|
||||
"react/jsx-no-constructed-context-values": "off",
|
||||
"react/no-array-index-key": "off",
|
||||
"react/forbid-elements": "off",
|
||||
// This would be good to enable in the future
|
||||
"typescript/await-thenable": "off",
|
||||
|
||||
+2
@@ -104,6 +104,8 @@ export const RoomListPrimaryFilters = memo(function RoomListPrimaryFilters({
|
||||
<ChatFilter
|
||||
key={`${filterId}-${index}`}
|
||||
role="option"
|
||||
tabIndex={0}
|
||||
aria-selected={filterId === activeFilterId}
|
||||
selected={filterId === activeFilterId}
|
||||
onClick={() => onToggleFilter(filterId)}
|
||||
>
|
||||
|
||||
+2
@@ -376,6 +376,8 @@ export function ActionBarView({ vm, className }: Readonly<ActionBarViewProps>):
|
||||
return (
|
||||
<RovingTabIndexProvider key={rovingProviderKey} handleLeftRight handleHomeEnd handleLoop>
|
||||
{({ onKeyDownHandler }) => (
|
||||
// This may be wrong but seems to work, this is a roving-toolbar, so the focus follows one of the children
|
||||
// oxlint-disable-next-line jsx-a11y/interactive-supports-focus
|
||||
<Flex
|
||||
display="inline-flex"
|
||||
direction="row"
|
||||
|
||||
Reference in New Issue
Block a user