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
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
|
||||
import React from "react";
|
||||
import { RoomMember } from "matrix-js-sdk/src/matrix";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
|
@ -29,7 +30,6 @@ import Heading from "../typography/Heading";
|
|||
import AccessibleButton from "./AccessibleButton";
|
||||
import { parseUrl } from "../../../utils/UrlUtils";
|
||||
import { Icon as HelpIcon } from "../../../../res/img/feather-customised/help-circle.svg";
|
||||
import TooltipTarget from "./TooltipTarget";
|
||||
|
||||
interface IProps {
|
||||
url: string;
|
||||
|
@ -99,31 +99,27 @@ export default class AppPermission extends React.Component<IProps, IState> {
|
|||
<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 = (
|
||||
<TooltipTarget
|
||||
label={warningTooltipText}
|
||||
tooltipClassName="mx_Tooltip--appPermission mx_Tooltip--appPermission--dark"
|
||||
tooltipTargetClassName="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon"
|
||||
className="mx_TextWithTooltip_tooltip"
|
||||
<Tooltip
|
||||
label={_t("analytics|shared_data_heading")}
|
||||
caption={
|
||||
<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>
|
||||
}
|
||||
>
|
||||
<HelpIcon className="mx_Icon mx_Icon_12" />
|
||||
</TooltipTarget>
|
||||
<div className="mx_TextWithTooltip_target mx_TextWithTooltip_target--helpIcon">
|
||||
<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.
|
||||
|
|
|
@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
|
|||
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 classNames from "classnames";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
|
||||
import { useTopic } from "../../../hooks/room/useTopic";
|
||||
import { Alignment } from "./Tooltip";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
|
@ -28,7 +28,6 @@ import InfoDialog from "../dialogs/InfoDialog";
|
|||
import { useDispatcher } from "../../../hooks/useDispatcher";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
import TooltipTarget from "./TooltipTarget";
|
||||
import { Linkify, topicToHtml } from "../../../HtmlUtils";
|
||||
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 {
|
||||
const client = useContext(MatrixClientContext);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [disableTooltip, setDisableTooltip] = useState(false);
|
||||
|
||||
const topic = useTopic(room);
|
||||
const body = topicToHtml(topic?.text, topic?.html, ref);
|
||||
const body = topicToHtml(topic?.text, topic?.html);
|
||||
|
||||
const onClick = useCallback(
|
||||
(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
|
@ -70,14 +69,14 @@ export default function RoomTopic({ room, className, ...props }: IProps): JSX.El
|
|||
[props],
|
||||
);
|
||||
|
||||
const ignoreHover = (ev: React.MouseEvent): boolean => {
|
||||
return (ev.target as HTMLElement).tagName.toUpperCase() === "A";
|
||||
const onHover = (ev: React.MouseEvent | React.FocusEvent): void => {
|
||||
setDisableTooltip((ev.target as HTMLElement).tagName.toUpperCase() === "A");
|
||||
};
|
||||
|
||||
useDispatcher(dis, (payload) => {
|
||||
if (payload.action === Action.ShowRoomTopic) {
|
||||
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, {
|
||||
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 (
|
||||
<TooltipTarget
|
||||
{...props}
|
||||
ref={ref}
|
||||
onClick={onClick}
|
||||
dir="auto"
|
||||
tooltipTargetClassName={classNames(className, "mx_RoomTopic")}
|
||||
label={_t("room|read_topic")}
|
||||
alignment={Alignment.Bottom}
|
||||
ignoreHover={ignoreHover}
|
||||
>
|
||||
<Linkify>{body}</Linkify>
|
||||
</TooltipTarget>
|
||||
<Tooltip label={_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")}
|
||||
>
|
||||
<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 { MatrixEvent, ClientEvent, ClientEventHandlerMap } from "matrix-js-sdk/src/matrix";
|
||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
|
||||
import { _t } from "../../../languageHandler";
|
||||
import Modal from "../../../Modal";
|
||||
|
@ -27,8 +28,6 @@ import {
|
|||
isSelfLocation,
|
||||
} from "../../../utils/location";
|
||||
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
||||
import TooltipTarget from "../elements/TooltipTarget";
|
||||
import { Alignment } from "../elements/Tooltip";
|
||||
import { SmartMarker, Map, LocationViewDialog } from "../location";
|
||||
import { IBodyProps } from "./IBodyProps";
|
||||
import { createReconnectedListener } from "../../../utils/connection";
|
||||
|
@ -126,7 +125,7 @@ export const LocationBodyFallbackContent: React.FC<{ event: MatrixEvent; error:
|
|||
interface LocationBodyContentProps {
|
||||
mxEvent: MatrixEvent;
|
||||
mapId: string;
|
||||
tooltip?: string;
|
||||
tooltip: string;
|
||||
onError: (error: Error) => void;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
@ -156,13 +155,9 @@ export const LocationBodyContent: React.FC<LocationBodyContentProps> = ({
|
|||
|
||||
return (
|
||||
<div className="mx_MLocationBody">
|
||||
{tooltip ? (
|
||||
<TooltipTarget label={tooltip} alignment={Alignment.InnerBottom} maxParentWidth={450}>
|
||||
{mapElement}
|
||||
</TooltipTarget>
|
||||
) : (
|
||||
mapElement
|
||||
)}
|
||||
<Tooltip label={tooltip}>
|
||||
<div className="mx_MLocationBody_map">{mapElement}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue