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:
parent
8e962f6897
commit
99ac9e5029
22 changed files with 133 additions and 43 deletions
|
@ -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) {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue