mirror of
https://github.com/smittix/intercept.git
synced 2026-05-02 10:39:58 -07:00
Fix proximity radar hover jitter without breaking device rendering
Replace capture-phase mouseenter/mouseleave with bubbling mouseover/mouseout for tracking hover state in the ProximityRadar component. The capture-phase approach caused two problems: 1. Moving between sibling child elements (hit-area → dot circle) fired mouseleave, prematurely clearing isHovered and triggering a DOM rebuild that caused visible jitter. 2. When renderDevices() rebuilt innerHTML, the browser fired mouseleave for the destroyed element with relatedTarget pointing at the newly created element at the same position, leaving isHovered permanently stuck at true and suppressing all future renders. The fix uses mouseover/mouseout (which bubble) with devicesGroup.contains() to reliably detect whether the cursor genuinely left the device group, immune to innerHTML rebuilds. Fixes both WiFi and Bluetooth proximity radars as they share this component. Closes #143. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -134,21 +134,28 @@ const ProximityRadar = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
devicesGroup.addEventListener('mouseenter', (e) => {
|
||||
// mouseover/mouseout bubble, so we get events from all descendants.
|
||||
// Use devicesGroup.contains(relatedTarget) to detect true entry/exit
|
||||
// rather than capture-phase mouseenter/mouseleave, which can leave
|
||||
// isHovered stuck when innerHTML is rebuilt under the cursor.
|
||||
devicesGroup.addEventListener('mouseover', (e) => {
|
||||
if (e.target.closest('.radar-device')) {
|
||||
isHovered = true;
|
||||
}
|
||||
}, true); // capture phase so we catch enter on child elements
|
||||
});
|
||||
|
||||
devicesGroup.addEventListener('mouseleave', (e) => {
|
||||
if (e.target.closest('.radar-device')) {
|
||||
devicesGroup.addEventListener('mouseout', (e) => {
|
||||
if (!e.target.closest('.radar-device')) return;
|
||||
// Only clear hover when the mouse leaves the group entirely —
|
||||
// moving between sibling children keeps relatedTarget inside the group.
|
||||
if (!devicesGroup.contains(e.relatedTarget)) {
|
||||
isHovered = false;
|
||||
if (renderPending) {
|
||||
renderPending = false;
|
||||
renderDevices();
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
// Add sweep animation
|
||||
animateSweep();
|
||||
|
||||
Reference in New Issue
Block a user