Fix eye button tap on touch devices in details panel

On touch devices, tapping an eye button in the details panel would
trigger chart mouseout → showDefaultView() which rebuilt the DOM
before the click event fired. Added pointerdown/pointerup guards
on the details box to prevent the race condition.

Also added @media (pointer: coarse) to always show eye buttons
on touch devices regardless of viewport width.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Anton Volnuhin 2026-02-08 01:01:00 +03:00
parent 7e87a03b90
commit bda882d89a

22
app.js
View File

@ -3243,7 +3243,20 @@ function setupHoverEvents(sunburstData, contextName = null) {
// Track if we're inside a section to handle sector exit properly
let isInsideSection = false;
// Prevent details panel reset when user is interacting with it (touch devices)
let isInteractingWithDetails = false;
const detailsBox = document.getElementById('details-box');
if (detailsBox) {
detailsBox.addEventListener('pointerdown', () => {
isInteractingWithDetails = true;
});
// Clear after a short delay to allow click handlers to fire
detailsBox.addEventListener('pointerup', () => {
setTimeout(() => { isInteractingWithDetails = false; }, 300);
});
}
// Add general mousemove event listener to detect when outside chart circle
chartDom.addEventListener('mousemove', function(e) {
// Get mouse position relative to chart container
@ -3256,7 +3269,7 @@ function setupHoverEvents(sunburstData, contextName = null) {
lastMouseY = mouseY;
// If not inside the chart circle and we were inside a section, show default view
if (!isInsideChart(mouseX, mouseY) && isInsideSection) {
if (!isInsideChart(mouseX, mouseY) && isInsideSection && !isInteractingWithDetails) {
isInsideSection = false;
// Reset details immediately when leaving a section
showDefaultView();
@ -3403,7 +3416,7 @@ function setupHoverEvents(sunburstData, contextName = null) {
hideChartEyeButton();
// Reset details with a small delay to allow mouseover of next sector to fire first
setTimeout(() => {
if (!isOverEyeButton && !isInsideSection) {
if (!isOverEyeButton && !isInsideSection && !isInteractingWithDetails) {
showDefaultView();
}
}, 50);
@ -3416,6 +3429,7 @@ function setupHoverEvents(sunburstData, contextName = null) {
if (e.relatedTarget === chartEyeBtn || (e.relatedTarget && chartEyeBtn.contains(e.relatedTarget))) {
return;
}
if (isInteractingWithDetails) return;
isInsideSection = false;
showDefaultView();
});
@ -3424,7 +3438,7 @@ function setupHoverEvents(sunburstData, contextName = null) {
myChart.on('downplay', function(params) {
// Reset to default view when a section is no longer emphasized (unless hovering eye button or still in section)
setTimeout(() => {
if (!isOverEyeButton && !isInsideSection) {
if (!isOverEyeButton && !isInsideSection && !isInteractingWithDetails) {
showDefaultView();
}
}, 50);