Migrate TooltipTarget
usage to compound Tooltip
(#12542)
* Use new tooltip in `RoomTopic.tsx` * Use new tooltip in `MLocationBody.tsx` * Fix room topic * Update location snapshot * Use new tooltip in `AppPermission.tsx` * Remove `TooltipTarget` * Add tests for `RoomTopic`
This commit is contained in:
parent
a29cabe45a
commit
1190de9028
12 changed files with 91 additions and 384 deletions
Binary file not shown.
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 18 KiB |
|
@ -44,24 +44,3 @@ limitations under the License.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_Tooltip.mx_Tooltip--appPermission {
|
|
||||||
box-shadow: none;
|
|
||||||
background-color: $tooltip-timeline-bg-color;
|
|
||||||
color: $tooltip-timeline-fg-color;
|
|
||||||
border: none;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 6px 8px;
|
|
||||||
|
|
||||||
&.mx_Tooltip--appPermission--dark {
|
|
||||||
.mx_Tooltip_chevron::after {
|
|
||||||
border-right-color: $tooltip-timeline-bg-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-position: inside;
|
|
||||||
padding-left: 2px;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
||||||
|
import { Tooltip } from "@vector-im/compound-web";
|
||||||
|
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import SdkConfig from "../../../SdkConfig";
|
import SdkConfig from "../../../SdkConfig";
|
||||||
|
@ -29,7 +30,6 @@ import Heading from "../typography/Heading";
|
||||||
import AccessibleButton from "./AccessibleButton";
|
import AccessibleButton from "./AccessibleButton";
|
||||||
import { parseUrl } from "../../../utils/UrlUtils";
|
import { parseUrl } from "../../../utils/UrlUtils";
|
||||||
import { Icon as HelpIcon } from "../../../../res/img/feather-customised/help-circle.svg";
|
import { Icon as HelpIcon } from "../../../../res/img/feather-customised/help-circle.svg";
|
||||||
import TooltipTarget from "./TooltipTarget";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -99,31 +99,27 @@ export default class AppPermission extends React.Component<IProps, IState> {
|
||||||
<BaseAvatar name={this.props.creatorUserId} size="38px" />
|
<BaseAvatar name={this.props.creatorUserId} size="38px" />
|
||||||
);
|
);
|
||||||
|
|
||||||
const warningTooltipText = (
|
|
||||||
<div>
|
|
||||||
{_t("analytics|shared_data_heading")}
|
|
||||||
<ul>
|
|
||||||
<li>{_t("widget|shared_data_name")}</li>
|
|
||||||
<li>{_t("widget|shared_data_avatar")}</li>
|
|
||||||
<li>{_t("widget|shared_data_mxid")}</li>
|
|
||||||
<li>{_t("widget|shared_data_device_id")}</li>
|
|
||||||
<li>{_t("widget|shared_data_theme")}</li>
|
|
||||||
<li>{_t("widget|shared_data_lang")}</li>
|
|
||||||
<li>{_t("widget|shared_data_url", { brand })}</li>
|
|
||||||
<li>{_t("widget|shared_data_room_id")}</li>
|
|
||||||
<li>{_t("widget|shared_data_widget_id")}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
const warningTooltip = (
|
const warningTooltip = (
|
||||||
<TooltipTarget
|
<Tooltip
|
||||||
label={warningTooltipText}
|
label={_t("analytics|shared_data_heading")}
|
||||||
tooltipClassName="mx_Tooltip--appPermission mx_Tooltip--appPermission--dark"
|
caption={
|
||||||
tooltipTargetClassName="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
|
<ul>
|
||||||
className="mx_TextWithTooltip_tooltip"
|
<li>{_t("widget|shared_data_name")}</li>
|
||||||
|
<li>{_t("widget|shared_data_avatar")}</li>
|
||||||
|
<li>{_t("widget|shared_data_mxid")}</li>
|
||||||
|
<li>{_t("widget|shared_data_device_id")}</li>
|
||||||
|
<li>{_t("widget|shared_data_theme")}</li>
|
||||||
|
<li>{_t("widget|shared_data_lang")}</li>
|
||||||
|
<li>{_t("widget|shared_data_url", { brand })}</li>
|
||||||
|
<li>{_t("widget|shared_data_room_id")}</li>
|
||||||
|
<li>{_t("widget|shared_data_widget_id")}</li>
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<HelpIcon className="mx_Icon mx_Icon_12" />
|
<div className="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon">
|
||||||
</TooltipTarget>
|
<HelpIcon className="mx_Icon mx_Icon_12" />
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|
||||||
// Due to i18n limitations, we can't dedupe the code for variables in these two messages.
|
// Due to i18n limitations, we can't dedupe the code for variables in these two messages.
|
||||||
|
|
|
@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useContext, useRef } from "react";
|
import React, { useCallback, useContext, useState } from "react";
|
||||||
import { Room, EventType } from "matrix-js-sdk/src/matrix";
|
import { Room, EventType } from "matrix-js-sdk/src/matrix";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import { Tooltip } from "@vector-im/compound-web";
|
||||||
|
|
||||||
import { useTopic } from "../../../hooks/room/useTopic";
|
import { useTopic } from "../../../hooks/room/useTopic";
|
||||||
import { Alignment } from "./Tooltip";
|
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import dis from "../../../dispatcher/dispatcher";
|
import dis from "../../../dispatcher/dispatcher";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
|
@ -28,7 +28,6 @@ import InfoDialog from "../dialogs/InfoDialog";
|
||||||
import { useDispatcher } from "../../../hooks/useDispatcher";
|
import { useDispatcher } from "../../../hooks/useDispatcher";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import AccessibleButton from "./AccessibleButton";
|
import AccessibleButton from "./AccessibleButton";
|
||||||
import TooltipTarget from "./TooltipTarget";
|
|
||||||
import { Linkify, topicToHtml } from "../../../HtmlUtils";
|
import { Linkify, topicToHtml } from "../../../HtmlUtils";
|
||||||
import { tryTransformPermalinkToLocalHref } from "../../../utils/permalinks/Permalinks";
|
import { tryTransformPermalinkToLocalHref } from "../../../utils/permalinks/Permalinks";
|
||||||
|
|
||||||
|
@ -49,10 +48,10 @@ export function onRoomTopicLinkClick(e: React.MouseEvent): void {
|
||||||
|
|
||||||
export default function RoomTopic({ room, className, ...props }: IProps): JSX.Element {
|
export default function RoomTopic({ room, className, ...props }: IProps): JSX.Element {
|
||||||
const client = useContext(MatrixClientContext);
|
const client = useContext(MatrixClientContext);
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const [disableTooltip, setDisableTooltip] = useState(false);
|
||||||
|
|
||||||
const topic = useTopic(room);
|
const topic = useTopic(room);
|
||||||
const body = topicToHtml(topic?.text, topic?.html, ref);
|
const body = topicToHtml(topic?.text, topic?.html);
|
||||||
|
|
||||||
const onClick = useCallback(
|
const onClick = useCallback(
|
||||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
|
@ -70,14 +69,14 @@ export default function RoomTopic({ room, className, ...props }: IProps): JSX.El
|
||||||
[props],
|
[props],
|
||||||
);
|
);
|
||||||
|
|
||||||
const ignoreHover = (ev: React.MouseEvent): boolean => {
|
const onHover = (ev: React.MouseEvent | React.FocusEvent): void => {
|
||||||
return (ev.target as HTMLElement).tagName.toUpperCase() === "A";
|
setDisableTooltip((ev.target as HTMLElement).tagName.toUpperCase() === "A");
|
||||||
};
|
};
|
||||||
|
|
||||||
useDispatcher(dis, (payload) => {
|
useDispatcher(dis, (payload) => {
|
||||||
if (payload.action === Action.ShowRoomTopic) {
|
if (payload.action === Action.ShowRoomTopic) {
|
||||||
const canSetTopic = room.currentState.maySendStateEvent(EventType.RoomTopic, client.getSafeUserId());
|
const canSetTopic = room.currentState.maySendStateEvent(EventType.RoomTopic, client.getSafeUserId());
|
||||||
const body = topicToHtml(topic?.text, topic?.html, ref, true);
|
const body = topicToHtml(topic?.text, topic?.html, undefined, true);
|
||||||
|
|
||||||
const modal = Modal.createDialog(InfoDialog, {
|
const modal = Modal.createDialog(InfoDialog, {
|
||||||
title: room.name,
|
title: room.name,
|
||||||
|
@ -115,18 +114,24 @@ export default function RoomTopic({ room, className, ...props }: IProps): JSX.El
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Do not render the tooltip if the topic is empty
|
||||||
|
// We still need to have a div for the header buttons to be displayed correctly
|
||||||
|
if (!body) return <div className={classNames(className, "mx_RoomTopic")} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TooltipTarget
|
<Tooltip label={_t("room|read_topic")} disabled={disableTooltip}>
|
||||||
{...props}
|
<div
|
||||||
ref={ref}
|
{...props}
|
||||||
onClick={onClick}
|
tabIndex={0}
|
||||||
dir="auto"
|
role="button"
|
||||||
tooltipTargetClassName={classNames(className, "mx_RoomTopic")}
|
onClick={onClick}
|
||||||
label={_t("room|read_topic")}
|
className={classNames(className, "mx_RoomTopic")}
|
||||||
alignment={Alignment.Bottom}
|
onMouseOver={onHover}
|
||||||
ignoreHover={ignoreHover}
|
onFocus={onHover}
|
||||||
>
|
aria-label={_t("room|read_topic")}
|
||||||
<Linkify>{body}</Linkify>
|
>
|
||||||
</TooltipTarget>
|
<Linkify>{body}</Linkify>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { forwardRef, HTMLAttributes, useRef } from "react";
|
|
||||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
|
||||||
|
|
||||||
import useFocus from "../../../hooks/useFocus";
|
|
||||||
import useHover from "../../../hooks/useHover";
|
|
||||||
import Tooltip, { ITooltipProps } from "./Tooltip";
|
|
||||||
|
|
||||||
interface IProps
|
|
||||||
extends HTMLAttributes<HTMLSpanElement>,
|
|
||||||
Omit<ITooltipProps, "visible" | "tabIndex" | "aria-describedby"> {
|
|
||||||
tooltipTargetClassName?: string;
|
|
||||||
ignoreHover?: (ev: React.MouseEvent) => boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic tooltip target element that handles tooltip visibility state
|
|
||||||
* and displays children
|
|
||||||
*/
|
|
||||||
const TooltipTarget = forwardRef<HTMLDivElement, IProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
children,
|
|
||||||
tooltipTargetClassName,
|
|
||||||
// tooltip pass through props
|
|
||||||
className,
|
|
||||||
id,
|
|
||||||
label,
|
|
||||||
alignment,
|
|
||||||
tooltipClassName,
|
|
||||||
maxParentWidth,
|
|
||||||
ignoreHover,
|
|
||||||
...rest
|
|
||||||
},
|
|
||||||
ref,
|
|
||||||
) => {
|
|
||||||
const idRef = useRef("mx_TooltipTarget_" + randomString(8));
|
|
||||||
// Use generated ID if one is not passed
|
|
||||||
if (id === undefined) {
|
|
||||||
id = idRef.current;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [isFocused, focusProps] = useFocus();
|
|
||||||
const [isHovering, hoverProps] = useHover(ignoreHover || (() => false));
|
|
||||||
|
|
||||||
// No need to fill up the DOM with hidden tooltip elements. Only add the
|
|
||||||
// tooltip when we're hovering over the item (performance)
|
|
||||||
const tooltip = (isFocused || isHovering) && (
|
|
||||||
<Tooltip
|
|
||||||
id={id}
|
|
||||||
className={className}
|
|
||||||
tooltipClassName={tooltipClassName}
|
|
||||||
label={label}
|
|
||||||
alignment={alignment}
|
|
||||||
visible={isFocused || isHovering}
|
|
||||||
maxParentWidth={maxParentWidth}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
{...hoverProps}
|
|
||||||
{...focusProps}
|
|
||||||
tabIndex={0}
|
|
||||||
aria-describedby={id}
|
|
||||||
className={tooltipTargetClassName}
|
|
||||||
{...rest}
|
|
||||||
ref={ref}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
{tooltip}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export default TooltipTarget;
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { MatrixEvent, ClientEvent, ClientEventHandlerMap } from "matrix-js-sdk/src/matrix";
|
import { MatrixEvent, ClientEvent, ClientEventHandlerMap } from "matrix-js-sdk/src/matrix";
|
||||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||||
|
import { Tooltip } from "@vector-im/compound-web";
|
||||||
|
|
||||||
import { _t } from "../../../languageHandler";
|
import { _t } from "../../../languageHandler";
|
||||||
import Modal from "../../../Modal";
|
import Modal from "../../../Modal";
|
||||||
|
@ -27,8 +28,6 @@ import {
|
||||||
isSelfLocation,
|
isSelfLocation,
|
||||||
} from "../../../utils/location";
|
} from "../../../utils/location";
|
||||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||||
import TooltipTarget from "../elements/TooltipTarget";
|
|
||||||
import { Alignment } from "../elements/Tooltip";
|
|
||||||
import { SmartMarker, Map, LocationViewDialog } from "../location";
|
import { SmartMarker, Map, LocationViewDialog } from "../location";
|
||||||
import { IBodyProps } from "./IBodyProps";
|
import { IBodyProps } from "./IBodyProps";
|
||||||
import { createReconnectedListener } from "../../../utils/connection";
|
import { createReconnectedListener } from "../../../utils/connection";
|
||||||
|
@ -126,7 +125,7 @@ export const LocationBodyFallbackContent: React.FC<{ event: MatrixEvent; error:
|
||||||
interface LocationBodyContentProps {
|
interface LocationBodyContentProps {
|
||||||
mxEvent: MatrixEvent;
|
mxEvent: MatrixEvent;
|
||||||
mapId: string;
|
mapId: string;
|
||||||
tooltip?: string;
|
tooltip: string;
|
||||||
onError: (error: Error) => void;
|
onError: (error: Error) => void;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
@ -156,13 +155,9 @@ export const LocationBodyContent: React.FC<LocationBodyContentProps> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_MLocationBody">
|
<div className="mx_MLocationBody">
|
||||||
{tooltip ? (
|
<Tooltip label={tooltip}>
|
||||||
<TooltipTarget label={tooltip} alignment={Alignment.InnerBottom} maxParentWidth={450}>
|
<div className="mx_MLocationBody_map">{mapElement}</div>
|
||||||
{mapElement}
|
</Tooltip>
|
||||||
</TooltipTarget>
|
|
||||||
) : (
|
|
||||||
mapElement
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,10 +43,7 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_vY7Q4uEh"
|
|
||||||
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
|
||||||
tabindex="0"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -121,10 +118,7 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_vY7Q4uEh"
|
|
||||||
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
|
||||||
tabindex="0"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -284,10 +278,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_vY7Q4uEh"
|
|
||||||
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
|
||||||
tabindex="0"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -531,10 +522,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_vY7Q4uEh"
|
|
||||||
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
class="mx_LegacyRoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
|
||||||
tabindex="0"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -16,7 +16,8 @@ limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Room } from "matrix-js-sdk/src/matrix";
|
import { Room } from "matrix-js-sdk/src/matrix";
|
||||||
import { fireEvent, render, screen } from "@testing-library/react";
|
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
|
||||||
import { mkEvent, stubClient } from "../../../test-utils";
|
import { mkEvent, stubClient } from "../../../test-utils";
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
|
@ -33,9 +34,12 @@ describe("<RoomTopic/>", () => {
|
||||||
window.location.href = originalHref;
|
window.location.href = originalHref;
|
||||||
});
|
});
|
||||||
|
|
||||||
function runClickTest(topic: string, clickText: string) {
|
/**
|
||||||
|
* Create a room with the given topic
|
||||||
|
* @param topic
|
||||||
|
*/
|
||||||
|
function createRoom(topic: string) {
|
||||||
stubClient();
|
stubClient();
|
||||||
|
|
||||||
const room = new Room("!pMBteVpcoJRdCJxDmn:matrix.org", MatrixClientPeg.safeGet(), "@alice:example.org");
|
const room = new Room("!pMBteVpcoJRdCJxDmn:matrix.org", MatrixClientPeg.safeGet(), "@alice:example.org");
|
||||||
const topicEvent = mkEvent({
|
const topicEvent = mkEvent({
|
||||||
type: "m.room.topic",
|
type: "m.room.topic",
|
||||||
|
@ -45,11 +49,27 @@ describe("<RoomTopic/>", () => {
|
||||||
ts: 123,
|
ts: 123,
|
||||||
event: true,
|
event: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
room.addLiveEvents([topicEvent]);
|
room.addLiveEvents([topicEvent]);
|
||||||
|
|
||||||
render(<RoomTopic room={room} />);
|
return room;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a room and render it
|
||||||
|
* @param topic
|
||||||
|
*/
|
||||||
|
const renderRoom = (topic: string) => {
|
||||||
|
const room = createRoom(topic);
|
||||||
|
render(<RoomTopic room={room} />);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a room and click on the given text
|
||||||
|
* @param topic
|
||||||
|
* @param clickText
|
||||||
|
*/
|
||||||
|
function runClickTest(topic: string, clickText: string) {
|
||||||
|
renderRoom(topic);
|
||||||
fireEvent.click(screen.getByText(clickText));
|
fireEvent.click(screen.getByText(clickText));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,4 +98,18 @@ describe("<RoomTopic/>", () => {
|
||||||
expect(window.location.href).toEqual(expectedHref);
|
expect(window.location.href).toEqual(expectedHref);
|
||||||
expect(dis.fire).toHaveBeenCalledWith(Action.ShowRoomTopic);
|
expect(dis.fire).toHaveBeenCalledWith(Action.ShowRoomTopic);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should open the tooltip when hovering a text", async () => {
|
||||||
|
const topic = "room topic";
|
||||||
|
renderRoom(topic);
|
||||||
|
await userEvent.hover(screen.getByText(topic));
|
||||||
|
await waitFor(() => expect(screen.getByRole("tooltip", { name: "Click to read topic" })).toBeInTheDocument());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not open the tooltip when hovering a link", async () => {
|
||||||
|
const topic = "https://matrix.org";
|
||||||
|
renderRoom(topic);
|
||||||
|
await userEvent.hover(screen.getByText(topic));
|
||||||
|
await waitFor(() => expect(screen.queryByRole("tooltip", { name: "Click to read topic" })).toBeNull());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import { fireEvent, render } from "@testing-library/react";
|
|
||||||
|
|
||||||
import { Alignment } from "../../../../src/components/views/elements/Tooltip";
|
|
||||||
import TooltipTarget from "../../../../src/components/views/elements/TooltipTarget";
|
|
||||||
|
|
||||||
describe("<TooltipTarget />", () => {
|
|
||||||
const defaultProps = {
|
|
||||||
"tooltipTargetClassName": "test tooltipTargetClassName",
|
|
||||||
"className": "test className",
|
|
||||||
"tooltipClassName": "test tooltipClassName",
|
|
||||||
"label": "test label",
|
|
||||||
"alignment": Alignment.Left,
|
|
||||||
"id": "test id",
|
|
||||||
"data-testid": "test",
|
|
||||||
};
|
|
||||||
|
|
||||||
const getComponent = (props = {}) => {
|
|
||||||
const wrapper = render(
|
|
||||||
// wrap in element so renderIntoDocument can render functional component
|
|
||||||
<span>
|
|
||||||
<TooltipTarget {...defaultProps} {...props}>
|
|
||||||
<span>child</span>
|
|
||||||
</TooltipTarget>
|
|
||||||
</span>,
|
|
||||||
);
|
|
||||||
return wrapper.getByTestId("test");
|
|
||||||
};
|
|
||||||
|
|
||||||
const getVisibleTooltip = () => document.querySelector(".mx_Tooltip.mx_Tooltip_visible");
|
|
||||||
|
|
||||||
it("renders container", () => {
|
|
||||||
const component = getComponent();
|
|
||||||
expect(component).toMatchSnapshot();
|
|
||||||
expect(getVisibleTooltip()).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
const alignmentKeys = Object.keys(Alignment).filter((o: any) => isNaN(o));
|
|
||||||
it.each(alignmentKeys)("displays %s aligned tooltip on mouseover", async (alignment: any) => {
|
|
||||||
const wrapper = getComponent({ alignment: Alignment[alignment] })!;
|
|
||||||
fireEvent.mouseOver(wrapper);
|
|
||||||
expect(getVisibleTooltip()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("hides tooltip on mouseleave", () => {
|
|
||||||
const wrapper = getComponent()!;
|
|
||||||
fireEvent.mouseOver(wrapper);
|
|
||||||
expect(getVisibleTooltip()).toBeTruthy();
|
|
||||||
fireEvent.mouseLeave(wrapper);
|
|
||||||
expect(getVisibleTooltip()).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("displays tooltip on focus", () => {
|
|
||||||
const wrapper = getComponent()!;
|
|
||||||
fireEvent.focus(wrapper);
|
|
||||||
expect(getVisibleTooltip()).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("hides tooltip on blur", async () => {
|
|
||||||
const wrapper = getComponent()!;
|
|
||||||
fireEvent.focus(wrapper);
|
|
||||||
expect(getVisibleTooltip()).toBeTruthy();
|
|
||||||
fireEvent.blur(wrapper);
|
|
||||||
expect(getVisibleTooltip()).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -288,9 +288,7 @@ exports[`AppTile for a pinned widget should render permission request 1`] = `
|
||||||
<span>
|
<span>
|
||||||
Using this widget may share data
|
Using this widget may share data
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_vY7Q4uEh"
|
|
||||||
class="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
|
class="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_Icon mx_Icon_12"
|
class="mx_Icon mx_Icon_12"
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays Bottom aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; top: 6px; transform: translate(max(10px, min(calc(0px - 50%), calc(100vw - 100% - 10px))));"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays InnerBottom aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; top: -50px; transform: translate(max(10px, min(calc(0px - 50%), calc(100vw - 100% - 10px))));"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays Left aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; right: 1030px; top: 0px; transform: translateY(-50%);"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays Natural aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; left: 6px; top: 0px; transform: translateY(-50%);"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays Right aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; left: 6px; top: 0px; transform: translateY(-50%);"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays Top aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; top: -6px; transform: translate(max(10px, min(calc(0px - 50%), calc(100vw - 100% - 10px))), -100%);"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> displays TopRight aligned tooltip on mouseover 1`] = `
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip test tooltipClassName mx_Tooltip_visible"
|
|
||||||
id="test id"
|
|
||||||
role="tooltip"
|
|
||||||
style="display: block; top: -6px; right: 1024px; transform: translateY(-100%);"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="mx_Tooltip_chevron"
|
|
||||||
/>
|
|
||||||
test label
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`<TooltipTarget /> renders container 1`] = `
|
|
||||||
<div
|
|
||||||
aria-describedby="test id"
|
|
||||||
class="test tooltipTargetClassName"
|
|
||||||
data-testid="test"
|
|
||||||
tabindex="0"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
child
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -34,8 +34,7 @@ exports[`MLocationBody <MLocationBody> without error renders map correctly 1`] =
|
||||||
class="mx_MLocationBody"
|
class="mx_MLocationBody"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_9K38QgU2"
|
class="mx_MLocationBody_map"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_Map mx_MLocationBody_map"
|
class="mx_Map mx_MLocationBody_map"
|
||||||
|
@ -67,8 +66,7 @@ exports[`MLocationBody <MLocationBody> without error renders marker correctly fo
|
||||||
class="mx_MLocationBody"
|
class="mx_MLocationBody"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-describedby="mx_TooltipTarget_9K38QgU2"
|
class="mx_MLocationBody_map"
|
||||||
tabindex="0"
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_Map mx_MLocationBody_map"
|
class="mx_Map mx_MLocationBody_map"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue