Switch Pill & E2EIcon to using Compound Tooltips (#12080)

* Switch Pill to using Compound Tooltips

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Switch E2EIcon to using Compound Tooltips

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update tests & snapshots

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2023-12-21 15:21:41 +00:00 committed by GitHub
parent 42ac2272b2
commit 07747e24d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 105 additions and 129 deletions

View file

@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactElement, useRef, useState } from "react";
import React, { ReactElement } from "react";
import classNames from "classnames";
import { Room, RoomMember } from "matrix-js-sdk/src/matrix";
import { Tooltip } from "@vector-im/compound-web";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import Tooltip, { Alignment } from "../elements/Tooltip";
import { usePermalink } from "../../../hooks/usePermalink";
import RoomAvatar from "../avatars/RoomAvatar";
import MemberAvatar from "../avatars/MemberAvatar";
@ -88,8 +88,6 @@ 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,
type: propType,
@ -109,15 +107,6 @@ export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room
mx_EventPill: type === PillType.EventInOtherRoom || type === PillType.EventInSameRoom,
});
const onMouseOver = (): void => {
setHover(true);
};
const onMouseLeave = (): void => {
setHover(false);
};
const tip = hover && resourceId ? <Tooltip id={tooltipId} label={resourceId} alignment={Alignment.Right} /> : null;
let avatar: ReactElement | null = null;
let pillText: string | null = text;
@ -155,34 +144,28 @@ export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room
return null;
}
const isAnchor = !!inMessage && !!url;
return (
<bdi>
<MatrixClientContext.Provider value={MatrixClientPeg.safeGet()}>
{inMessage && url ? (
<a
className={classes}
href={url}
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}
aria-describedby={tooltipId}
>
{avatar}
<span className="mx_Pill_text">{pillText}</span>
{tip}
</span>
)}
<Tooltip
label={resourceId ?? ""}
open={resourceId ? undefined : false}
side="right"
isTriggerInteractive={isAnchor}
>
{isAnchor ? (
<a className={classes} href={url} onClick={onClick}>
{avatar}
<span className="mx_Pill_text">{pillText}</span>
</a>
) : (
<span className={classes}>
{avatar}
<span className="mx_Pill_text">{pillText}</span>
</span>
)}
</Tooltip>
</MatrixClientContext.Provider>
</bdi>
);

View file

@ -15,12 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { CSSProperties, useState } from "react";
import React, { ComponentProps, CSSProperties } from "react";
import classNames from "classnames";
import { Tooltip } from "@vector-im/compound-web";
import { _t, _td, TranslationKey } from "../../../languageHandler";
import AccessibleButton from "../elements/AccessibleButton";
import Tooltip, { Alignment } from "../elements/Tooltip";
import { E2EStatus } from "../../../utils/ShieldUtils";
import { XOR } from "../../../@types/common";
@ -48,7 +48,7 @@ interface Props {
size?: number;
onClick?: () => void;
hideTooltip?: boolean;
tooltipAlignment?: Alignment;
tooltipSide?: ComponentProps<typeof Tooltip>["side"];
bordered?: boolean;
}
@ -69,11 +69,9 @@ const E2EIcon: React.FC<XOR<UserProps, RoomProps>> = ({
size,
onClick,
hideTooltip,
tooltipAlignment,
tooltipSide,
bordered,
}) => {
const [hover, setHover] = useState(false);
const classes = classNames(
{
mx_E2EIcon: true,
@ -97,35 +95,23 @@ const E2EIcon: React.FC<XOR<UserProps, RoomProps>> = ({
style = { width: `${size}px`, height: `${size}px` };
}
const onMouseOver = (): void => setHover(true);
const onMouseLeave = (): void => setHover(false);
const label = e2eTitle ? _t(e2eTitle) : "";
let tip: JSX.Element | undefined;
if (hover && !hideTooltip && label) {
tip = <Tooltip label={label} alignment={tooltipAlignment} />;
let content: JSX.Element;
if (onClick) {
content = <AccessibleButton onClick={onClick} className={classes} style={style} />;
} else {
content = <div className={classes} style={style} />;
}
if (onClick) {
return (
<AccessibleButton
onClick={onClick}
onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave}
className={classes}
style={style}
aria-label={label}
>
{tip}
</AccessibleButton>
);
if (!e2eTitle || hideTooltip) {
return content;
}
return (
<div onMouseOver={onMouseOver} onMouseLeave={onMouseLeave} className={classes} style={style} aria-label={label}>
{tip}
</div>
<Tooltip label={label} side={tooltipSide} isTriggerInteractive={!!onClick}>
{content}
</Tooltip>
);
};

View file

@ -780,11 +780,7 @@ export default class RoomHeader extends React.Component<IProps, IState> {
const icon = this.props.viewingCall ? (
<div className="mx_LegacyRoomHeader_icon mx_LegacyRoomHeader_icon_video" />
) : this.props.e2eStatus ? (
<E2EIcon
className="mx_LegacyRoomHeader_icon"
status={this.props.e2eStatus}
tooltipAlignment={Alignment.Bottom}
/>
<E2EIcon className="mx_LegacyRoomHeader_icon" status={this.props.e2eStatus} tooltipSide="bottom" />
) : // If we're expecting an E2EE status to come in, but it hasn't
// yet been loaded, insert a blank div to reserve space
this.client.isRoomEncrypted(this.props.room.roomId) && this.client.isCryptoEnabled() ? (