Ensure tooltip contents is linked via aria to the target element (#10729)

* Ensure tooltip contents is linked via aria to the target element

* Iterate

* Fix tests

* Fix tests

* Update snapshot

* Fix missing aria labels for more tooltips

* Iterate

* Update snapshots
This commit is contained in:
Michael Telatynski 2023-05-05 09:26:11 +01:00 committed by GitHub
parent 8e962f6897
commit 99ac9e5029
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 133 additions and 43 deletions

View file

@ -18,7 +18,9 @@ import React from "react";
import TextWithTooltip from "./TextWithTooltip";
interface IProps extends Omit<React.ComponentProps<typeof TextWithTooltip>, "tabIndex" | "onClick"> {}
interface IProps extends Omit<React.ComponentProps<typeof TextWithTooltip>, "tabIndex" | "onClick" | "tooltip"> {
tooltip: string;
}
export default class LinkWithTooltip extends React.Component<IProps> {
public constructor(props: IProps) {

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactElement, useState } from "react";
import React, { ReactElement, useRef, useState } from "react";
import classNames from "classnames";
import { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/matrix";
@ -89,6 +89,7 @@ export interface PillProps {
}
export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room, shouldShowPillAvatar = true }) => {
const tooltipId = useRef(`mx_Pill_${Math.random()}`).current;
const [hover, setHover] = useState(false);
const { event, member, onClick, resourceId, targetRoom, text, type } = usePermalink({
room,
@ -117,7 +118,7 @@ export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room
setHover(false);
};
const tip = hover && resourceId ? <Tooltip label={resourceId} alignment={Alignment.Right} /> : null;
const tip = hover && resourceId ? <Tooltip id={tooltipId} label={resourceId} alignment={Alignment.Right} /> : null;
let avatar: ReactElement | null = null;
let pillText: string | null = text;
@ -165,13 +166,19 @@ export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room
onClick={onClick}
onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave}
aria-describedby={tooltipId}
>
{avatar}
<span className="mx_Pill_text">{pillText}</span>
{tip}
</a>
) : (
<span className={classes} onMouseOver={onMouseOver} onMouseLeave={onMouseLeave}>
<span
className={classes}
onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave}
aria-describedby={tooltipId}
>
{avatar}
<span className="mx_Pill_text">{pillText}</span>
{tip}

View file

@ -35,6 +35,10 @@ export default class TextWithTooltip extends React.Component<IProps> {
public render(): React.ReactNode {
const { class: className, children, tooltip, tooltipClass, tooltipProps, ...props } = this.props;
if (typeof tooltip === "string") {
props["aria-label"] = tooltip;
}
return (
<TooltipTarget
onClick={this.props.onClick}

View file

@ -188,7 +188,7 @@ export default class Tooltip extends React.PureComponent<ITooltipProps, State> {
style.display = this.props.visible ? "block" : "none";
const tooltip = (
<div role={this.props.role || "tooltip"} className={tooltipClasses} style={style}>
<div id={this.props.id} role={this.props.role || "tooltip"} className={tooltipClasses} style={style}>
<div className="mx_Tooltip_chevron" />
{this.props.label}
</div>