From e1a426bde49643f875bd5747ac2fd7614f8f51fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Mummert?= Date: Sun, 5 Apr 2026 13:40:57 +0200 Subject: [PATCH] Handle skipped view transition promises in event filter --- .../templates/frontend/event_filter.html.twig | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/contao/templates/frontend/event_filter.html.twig b/contao/templates/frontend/event_filter.html.twig index 159e336..1d330a8 100644 --- a/contao/templates/frontend/event_filter.html.twig +++ b/contao/templates/frontend/event_filter.html.twig @@ -132,6 +132,7 @@ const animationMs = 220; let hideTimers = new WeakMap(); const supportsViewTransitions = typeof document.startViewTransition === 'function'; + let activeViewTransition = null; let isViewTransitionMutation = false; let currentFilter = { type: 'all', value: '' }; let suppressedChangeEvents = 0; @@ -142,8 +143,13 @@ return; } + if (activeViewTransition) { + mutation(); + return; + } + try { - document.startViewTransition(() => { + const transition = document.startViewTransition(() => { isViewTransitionMutation = true; try { @@ -152,6 +158,26 @@ isViewTransitionMutation = false; } }); + + activeViewTransition = transition; + + transition.ready.catch(() => { + // Can reject when the transition is skipped. + }); + + transition.updateCallbackDone.catch(() => { + // Keep skipped/aborted update callbacks from surfacing as uncaught. + }); + + transition.finished + .catch(() => { + // Browsers can skip overlapping transitions; ignore these rejections. + }) + .finally(() => { + if (activeViewTransition === transition) { + activeViewTransition = null; + } + }); } catch (error) { mutation(); } @@ -293,13 +319,7 @@ clearHideTimer(eventItem); if (eventItem.hidden) { - if (supportsViewTransitions && !isViewTransitionMutation) { - runWithLayoutTransition(() => { - eventItem.hidden = false; - }); - } else { - eventItem.hidden = false; - } + eventItem.hidden = false; } requestAnimationFrame(() => { @@ -312,13 +332,7 @@ eventItem.classList.add('is-filtered-out'); const timer = window.setTimeout(() => { - if (supportsViewTransitions && !isViewTransitionMutation) { - runWithLayoutTransition(() => { - eventItem.hidden = true; - }); - } else { - eventItem.hidden = true; - } + eventItem.hidden = true; hideTimers.delete(eventItem); }, animationMs);