Skip to content

Commit 336fac7

Browse files
committed
fix: debounce hover updates for accurate element positioning
1 parent 3bd36be commit 336fac7

1 file changed

Lines changed: 34 additions & 16 deletions

File tree

src/view/frontend/web/js/inspector.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ document.addEventListener('alpine:init', () => {
1515
floatingButton: null,
1616
mouseMoveHandler: null,
1717
clickHandler: null,
18+
hoverTimeout: null,
19+
hoverDelay: 50, // ms delay for accurate position calculation
1820
lastBadgeUpdate: 0,
1921
badgeUpdateDelay: 150, // ms delay to prevent flickering
2022
panelData: {
@@ -94,7 +96,7 @@ document.addEventListener('alpine:init', () => {
9496
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
9597
font-size: 11px;
9698
line-height: 1.6;
97-
pointer-events: auto;
99+
pointer-events: none;
98100
z-index: 10000000;
99101
display: none;
100102
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(255, 255, 255, 0.05);
@@ -265,6 +267,13 @@ document.addEventListener('alpine:init', () => {
265267
*/
266268
deactivatePicker() {
267269
this.isPickerActive = false;
270+
271+
// Clear any pending hover timeout
272+
if (this.hoverTimeout) {
273+
clearTimeout(this.hoverTimeout);
274+
this.hoverTimeout = null;
275+
}
276+
268277
document.removeEventListener('mousemove', this.mouseMoveHandler);
269278
document.removeEventListener('click', this.clickHandler, false);
270279
document.body.style.cursor = '';
@@ -279,29 +288,37 @@ document.addEventListener('alpine:init', () => {
279288
handleMouseMove(e) {
280289
if (!this.isPickerActive) return;
281290

282-
// Don't update if mouse is over the info badge or floating button
283-
if ((this.infoBadge && this.infoBadge.contains(e.target)) ||
284-
(this.floatingButton && this.floatingButton.contains(e.target))) {
291+
// Don't update if mouse is over the floating button
292+
if (this.floatingButton && this.floatingButton.contains(e.target)) {
285293
return;
286294
}
287295

288296
const element = this.findInspectableElement(e.target);
289297

298+
// Clear any existing hover timeout
299+
if (this.hoverTimeout) {
300+
clearTimeout(this.hoverTimeout);
301+
this.hoverTimeout = null;
302+
}
303+
290304
if (element && element !== this.hoveredElement) {
291-
// Throttle badge updates to prevent flickering
292-
const now = Date.now();
293-
if (now - this.lastBadgeUpdate < this.badgeUpdateDelay) {
294-
// Only update highlight, keep badge
305+
// Debounce hover updates for accurate positioning
306+
this.hoverTimeout = setTimeout(() => {
307+
// Throttle badge updates to prevent flickering
308+
const now = Date.now();
309+
if (now - this.lastBadgeUpdate < this.badgeUpdateDelay) {
310+
// Only update highlight, keep badge
311+
this.hoveredElement = element;
312+
this.showHighlight(element);
313+
return;
314+
}
315+
295316
this.hoveredElement = element;
317+
this.lastBadgeUpdate = now;
296318
this.showHighlight(element);
297-
return;
298-
}
299-
300-
this.hoveredElement = element;
301-
this.lastBadgeUpdate = now;
302-
this.showHighlight(element);
303-
this.updatePanelData(element);
304-
this.showInfoBadge(element);
319+
this.updatePanelData(element);
320+
this.showInfoBadge(element);
321+
}, this.hoverDelay);
305322
} else if (!element && this.hoveredElement) {
306323
// Only hide highlight when leaving element, keep badge visible
307324
if (this.highlightBox) {
@@ -599,6 +616,7 @@ document.addEventListener('alpine:init', () => {
599616
width: 100%;
600617
box-sizing: border-box;
601618
font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
619+
pointer-events: auto;
602620
`;
603621
textSpan.textContent = text;
604622
textSpan.title = 'Click to copy';

0 commit comments

Comments
 (0)