Fix wrong room topic tooltip position (#10667)
* Fix wrong room topic tooltip position * Update snapshots * Fix tests
This commit is contained in:
parent
93b4ee654b
commit
1efa82917a
5 changed files with 101 additions and 97 deletions
|
@ -103,10 +103,17 @@ export default function RoomTopic({ room, ...props }: IProps): JSX.Element {
|
||||||
const className = classNames(props.className, "mx_RoomTopic");
|
const className = classNames(props.className, "mx_RoomTopic");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...props} ref={ref} onClick={onClick} dir="auto" className={className}>
|
<TooltipTarget
|
||||||
<TooltipTarget label={_t("Click to read topic")} alignment={Alignment.Bottom} ignoreHover={ignoreHover}>
|
{...props}
|
||||||
<Linkify>{body}</Linkify>
|
ref={ref}
|
||||||
</TooltipTarget>
|
onClick={onClick}
|
||||||
</div>
|
dir="auto"
|
||||||
|
tooltipTargetClassName={className}
|
||||||
|
label={_t("Click to read topic")}
|
||||||
|
alignment={Alignment.Bottom}
|
||||||
|
ignoreHover={ignoreHover}
|
||||||
|
>
|
||||||
|
<Linkify>{body}</Linkify>
|
||||||
|
</TooltipTarget>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { HTMLAttributes } from "react";
|
import React, { forwardRef, HTMLAttributes } from "react";
|
||||||
|
|
||||||
import useFocus from "../../../hooks/useFocus";
|
import useFocus from "../../../hooks/useFocus";
|
||||||
import useHover from "../../../hooks/useHover";
|
import useHover from "../../../hooks/useHover";
|
||||||
|
@ -29,49 +29,55 @@ interface IProps extends HTMLAttributes<HTMLSpanElement>, Omit<ITooltipProps, "v
|
||||||
* Generic tooltip target element that handles tooltip visibility state
|
* Generic tooltip target element that handles tooltip visibility state
|
||||||
* and displays children
|
* and displays children
|
||||||
*/
|
*/
|
||||||
const TooltipTarget: React.FC<IProps> = ({
|
const TooltipTarget = forwardRef<HTMLDivElement, IProps>(
|
||||||
children,
|
(
|
||||||
tooltipTargetClassName,
|
{
|
||||||
// tooltip pass through props
|
children,
|
||||||
className,
|
tooltipTargetClassName,
|
||||||
id,
|
// tooltip pass through props
|
||||||
label,
|
className,
|
||||||
alignment,
|
id,
|
||||||
tooltipClassName,
|
label,
|
||||||
maxParentWidth,
|
alignment,
|
||||||
ignoreHover,
|
tooltipClassName,
|
||||||
...rest
|
maxParentWidth,
|
||||||
}) => {
|
ignoreHover,
|
||||||
const [isFocused, focusProps] = useFocus();
|
...rest
|
||||||
const [isHovering, hoverProps] = useHover(ignoreHover || (() => false));
|
},
|
||||||
|
ref,
|
||||||
|
) => {
|
||||||
|
const [isFocused, focusProps] = useFocus();
|
||||||
|
const [isHovering, hoverProps] = useHover(ignoreHover || (() => false));
|
||||||
|
|
||||||
// No need to fill up the DOM with hidden tooltip elements. Only add the
|
// No need to fill up the DOM with hidden tooltip elements. Only add the
|
||||||
// tooltip when we're hovering over the item (performance)
|
// tooltip when we're hovering over the item (performance)
|
||||||
const tooltip = (isFocused || isHovering) && (
|
const tooltip = (isFocused || isHovering) && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
id={id}
|
id={id}
|
||||||
className={className}
|
className={className}
|
||||||
tooltipClassName={tooltipClassName}
|
tooltipClassName={tooltipClassName}
|
||||||
label={label}
|
label={label}
|
||||||
alignment={alignment}
|
alignment={alignment}
|
||||||
visible={isFocused || isHovering}
|
visible={isFocused || isHovering}
|
||||||
maxParentWidth={maxParentWidth}
|
maxParentWidth={maxParentWidth}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
{...hoverProps}
|
{...hoverProps}
|
||||||
{...focusProps}
|
{...focusProps}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
aria-describedby={id}
|
aria-describedby={id}
|
||||||
className={tooltipTargetClassName}
|
className={tooltipTargetClassName}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
ref={ref}
|
||||||
{children}
|
>
|
||||||
{tooltip}
|
{children}
|
||||||
</div>
|
{tooltip}
|
||||||
);
|
</div>
|
||||||
};
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export default TooltipTarget;
|
export default TooltipTarget;
|
||||||
|
|
|
@ -52,24 +52,27 @@ describe("PosthogAnalytics", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fakePosthog = getFakePosthog();
|
fakePosthog = getFakePosthog();
|
||||||
|
|
||||||
window.crypto = {
|
Object.defineProperty(window, "crypto", {
|
||||||
subtle: {
|
value: {
|
||||||
digest: async (_: AlgorithmIdentifier, encodedMessage: BufferSource) => {
|
subtle: {
|
||||||
const message = new TextDecoder().decode(encodedMessage);
|
digest: async (_: AlgorithmIdentifier, encodedMessage: BufferSource) => {
|
||||||
const hexHash = shaHashes[message];
|
const message = new TextDecoder().decode(encodedMessage);
|
||||||
const bytes: number[] = [];
|
const hexHash = shaHashes[message];
|
||||||
for (let c = 0; c < hexHash.length; c += 2) {
|
const bytes: number[] = [];
|
||||||
bytes.push(parseInt(hexHash.slice(c, c + 2), 16));
|
for (let c = 0; c < hexHash.length; c += 2) {
|
||||||
}
|
bytes.push(parseInt(hexHash.slice(c, c + 2), 16));
|
||||||
return bytes as unknown as ArrayBuffer;
|
}
|
||||||
|
return bytes;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
} as unknown as SubtleCrypto,
|
},
|
||||||
} as unknown as Crypto;
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
// @ts-ignore
|
Object.defineProperty(window, "crypto", {
|
||||||
window.crypto = null;
|
value: null,
|
||||||
|
});
|
||||||
SdkConfig.unset(); // we touch the config, so clean up
|
SdkConfig.unset(); // we touch the config, so clean up
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -55,14 +55,11 @@ exports[`RoomView for a local room in state CREATING should match the snapshot 1
|
||||||
<div
|
<div
|
||||||
class="mx_RoomHeader_topic mx_RoomTopic"
|
class="mx_RoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div
|
<span
|
||||||
tabindex="0"
|
dir="auto"
|
||||||
>
|
/>
|
||||||
<span
|
|
||||||
dir="auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -149,14 +146,11 @@ exports[`RoomView for a local room in state ERROR should match the snapshot 1`]
|
||||||
<div
|
<div
|
||||||
class="mx_RoomHeader_topic mx_RoomTopic"
|
class="mx_RoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div
|
<span
|
||||||
tabindex="0"
|
dir="auto"
|
||||||
>
|
/>
|
||||||
<span
|
|
||||||
dir="auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -339,14 +333,11 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<div
|
<div
|
||||||
class="mx_RoomHeader_topic mx_RoomTopic"
|
class="mx_RoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div
|
<span
|
||||||
tabindex="0"
|
dir="auto"
|
||||||
>
|
/>
|
||||||
<span
|
|
||||||
dir="auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -606,14 +597,11 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<div
|
<div
|
||||||
class="mx_RoomHeader_topic mx_RoomTopic"
|
class="mx_RoomHeader_topic mx_RoomTopic"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<div
|
<span
|
||||||
tabindex="0"
|
dir="auto"
|
||||||
>
|
/>
|
||||||
<span
|
|
||||||
dir="auto"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -75,13 +75,13 @@ describe("MegolmExportEncryption", function () {
|
||||||
let MegolmExportEncryption: typeof MegolmExportEncryptionExport;
|
let MegolmExportEncryption: typeof MegolmExportEncryptionExport;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
window.crypto = {
|
Object.defineProperty(window, "crypto", {
|
||||||
getRandomValues,
|
value: {
|
||||||
randomUUID: jest.fn().mockReturnValue("not-random-uuid"),
|
getRandomValues,
|
||||||
subtle: webCrypto.subtle,
|
randomUUID: jest.fn().mockReturnValue("not-random-uuid"),
|
||||||
};
|
subtle: webCrypto.subtle,
|
||||||
// @ts-ignore for some reason including it in the object above gets ignored
|
},
|
||||||
window.crypto.subtle = webCrypto.subtle;
|
});
|
||||||
MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
|
MegolmExportEncryption = require("../../src/utils/MegolmExportEncryption");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue