Fix account hovercard sometimes not triggering (#39381)

This commit is contained in:
diondiondion 2026-06-11 18:18:44 +02:00 committed by GitHub
parent 8ba8ce5669
commit 2e3b81cc1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -30,8 +30,8 @@ export const HoverCardController: React.FC = () => {
const cardRef = useRef<HTMLDivElement | null>(null); const cardRef = useRef<HTMLDivElement | null>(null);
const [setLeaveTimeout, cancelLeaveTimeout] = useTimeout(); const [setLeaveTimeout, cancelLeaveTimeout] = useTimeout();
const [setEnterTimeout, cancelEnterTimeout, delayEnterTimeout] = useTimeout(); const [setEnterTimeout, cancelEnterTimeout, delayEnterTimeout] = useTimeout();
const [setMoveTimeout, cancelMoveTimeout] = useTimeout();
const [setScrollTimeout] = useTimeout(); const [setScrollTimeout] = useTimeout();
const lastMouseMoveTime = useRef<number>(0);
const handleClose = useCallback(() => { const handleClose = useCallback(() => {
cancelEnterTimeout(); cancelEnterTimeout();
@ -50,7 +50,6 @@ export const HoverCardController: React.FC = () => {
useEffect(() => { useEffect(() => {
let isScrolling = false; let isScrolling = false;
let isUsingTouch = false; let isUsingTouch = false;
let isActiveMouseMovement = false;
let currentAnchor: HTMLElement | null = null; let currentAnchor: HTMLElement | null = null;
let currentTitle: string | null = null; let currentTitle: string | null = null;
@ -84,9 +83,17 @@ export const HoverCardController: React.FC = () => {
return; return;
} }
// This 0ms timeout is needed to push processing of this code
// until after the mousemove event was run, in order to be able
// to track the most recent value of lastMouseMoveTime.current
setTimeout(() => {
// Check if mouse moved within the active movement threshold
const timeSinceLastMove = Date.now() - lastMouseMoveTime.current;
const hasRecentMovement = timeSinceLastMove < activeMovementThreshold;
// Bail out if we're scrolling, a touch is active, // Bail out if we're scrolling, a touch is active,
// or if there was no active mouse movement // or if there was no active mouse movement
if (isScrolling || !isActiveMouseMovement || isUsingTouch) { if (isScrolling || !hasRecentMovement || isUsingTouch) {
return; return;
} }
@ -109,6 +116,7 @@ export const HoverCardController: React.FC = () => {
if (target === currentAnchor || target === cardRef.current) { if (target === currentAnchor || target === cardRef.current) {
cancelLeaveTimeout(); cancelLeaveTimeout();
} }
}, 0);
}; };
const handleMouseLeave = (e: MouseEvent) => { const handleMouseLeave = (e: MouseEvent) => {
@ -149,18 +157,15 @@ export const HoverCardController: React.FC = () => {
isUsingTouch = false; isUsingTouch = false;
} }
const hasMoved = Math.max(e.movementX, e.movementY) > 0; const hasMoved =
Math.max(Math.abs(e.movementX), Math.abs(e.movementY)) > 0;
if (!hasMoved) { if (!hasMoved) {
return; return;
} }
delayEnterTimeout(enterDelay); delayEnterTimeout(enterDelay);
lastMouseMoveTime.current = Date.now();
cancelMoveTimeout();
isActiveMouseMovement = true;
setMoveTimeout(() => {
isActiveMouseMovement = false;
}, activeMovementThreshold);
}; };
document.body.addEventListener('touchstart', handleTouchStart, { document.body.addEventListener('touchstart', handleTouchStart, {
@ -204,8 +209,6 @@ export const HoverCardController: React.FC = () => {
setOpen, setOpen,
setAccountId, setAccountId,
setAnchor, setAnchor,
setMoveTimeout,
cancelMoveTimeout,
]); ]);
return ( return (