Fix tooltips within context menu portals being unreliable (#31129)

* Fix tooltips within context menu portals being unreliable

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

* Update snapshots

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

* Add test

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

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2025-10-31 09:00:01 +00:00 committed by GitHub
parent bbb16f7ea9
commit c7f07f4c29
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 97 additions and 45 deletions

View File

@ -12,6 +12,7 @@ import React, { type JSX, type CSSProperties, type RefObject, type SyntheticEven
import ReactDOM from "react-dom";
import classNames from "classnames";
import FocusLock from "react-focus-lock";
import { TooltipProvider } from "@vector-im/compound-web";
import { type Writeable } from "../../@types/common";
import UIStore from "../../stores/UIStore";
@ -425,6 +426,7 @@ export default class ContextMenu extends React.PureComponent<React.PropsWithChil
onContextMenu={this.onContextMenuPreventBubbling}
>
{background}
<TooltipProvider>
<div
className={menuClasses}
style={menuStyle}
@ -434,6 +436,7 @@ export default class ContextMenu extends React.PureComponent<React.PropsWithChil
>
{body}
</div>
</TooltipProvider>
</div>
)}
</RovingTabIndexProvider>

View File

@ -212,8 +212,12 @@ export function ReadReceiptPerson({
onAfterClick,
}: ReadReceiptPersonProps): JSX.Element {
return (
<Tooltip description={roomMember?.rawDisplayName ?? userId} caption={userId} placement="top">
<div>
<Tooltip
description={roomMember?.rawDisplayName ?? userId}
caption={userId}
placement="top"
isTriggerInteractive={false}
>
<MenuItem
className="mx_ReadReceiptGroup_person"
onClick={() => {
@ -243,7 +247,6 @@ export function ReadReceiptPerson({
<p className="mx_ReadReceiptGroup_secondary">{formatDate(new Date(ts), isTwelveHour)}</p>
</div>
</MenuItem>
</div>
</Tooltip>
);
}

View File

@ -142,5 +142,10 @@ describe("ReadReceiptGroup", () => {
}),
);
});
it("should fall back to userId if roomMember unspecified", async () => {
const { container } = renderReadReceipt({ roomMember: null });
expect(container).toMatchSnapshot();
});
});
});

View File

@ -6,14 +6,14 @@ exports[`ReadReceiptGroup <ReadReceiptPerson /> should display a tooltip 1`] = `
data-floating-ui-focusable=""
id="_r_6_"
role="tooltip"
style="position: absolute; left: 0px; top: 0px; transform: translate(0px, 0px);"
style="position: absolute; left: 0px; top: 0px; transform: translate(5px, -6px);"
tabindex="-1"
>
<svg
aria-hidden="true"
class="_arrow_6ode6_33"
height="10"
style="position: absolute; pointer-events: none; top: 100%;"
style="position: absolute; pointer-events: none; top: 100%; left: -1px;"
viewBox="0 0 10 10"
width="10"
>
@ -46,9 +46,50 @@ exports[`ReadReceiptGroup <ReadReceiptPerson /> should display a tooltip 1`] = `
</div>
`;
exports[`ReadReceiptGroup <ReadReceiptPerson /> should fall back to userId if roomMember unspecified 1`] = `
<div>
<span
tabindex="0"
>
<div
class="mx_AccessibleButton mx_ReadReceiptGroup_person"
role="menuitem"
tabindex="-1"
>
<span
aria-hidden="true"
aria-live="off"
class="_avatar_1qbcf_8 mx_BaseAvatar _avatar-imageless_1qbcf_52"
data-color="3"
data-testid="avatar-img"
data-type="round"
role="presentation"
style="--cpd-avatar-size: 24px;"
>
a
</span>
<div
class="mx_ReadReceiptGroup_name"
>
<p>
@alice:example.org
</p>
<p
class="mx_ReadReceiptGroup_secondary"
>
==MOCK FORMATTED DATE==
</p>
</div>
</div>
</span>
</div>
`;
exports[`ReadReceiptGroup <ReadReceiptPerson /> should render 1`] = `
<div>
<div>
<span
tabindex="0"
>
<div
class="mx_AccessibleButton mx_ReadReceiptGroup_person"
role="menuitem"
@ -88,6 +129,6 @@ exports[`ReadReceiptGroup <ReadReceiptPerson /> should render 1`] = `
</p>
</div>
</div>
</div>
</span>
</div>
`;