From ef9d1cea3ea88f8ba26ebd0c45c13990068874ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vi=CC=81ctor=20CG?= Date: Thu, 15 Aug 2024 11:44:54 +0200 Subject: [PATCH] fix(staggered-fade-and-slide): use a DOM el filter to calculate stagger delay --- .../animations/staggered-fade-and-slide.vue | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/packages/x-components/src/components/animations/staggered-fade-and-slide.vue b/packages/x-components/src/components/animations/staggered-fade-and-slide.vue index 37110b031f..2e5ec7cc2f 100644 --- a/packages/x-components/src/components/animations/staggered-fade-and-slide.vue +++ b/packages/x-components/src/components/animations/staggered-fade-and-slide.vue @@ -2,7 +2,6 @@ void) { - const elIndex = +((el as HTMLElement).dataset.index ?? 0); - const staggerIndex = elIndex - staggerCounter.value; - const staggerDelay = staggerIndex * props.stagger; + function onEnter(el: HTMLElement, done: () => void) { + const elIndex = findAnimationIndex(el); + const staggerDelay = elIndex > 0 ? elIndex * props.stagger : 0; - (el as HTMLElement).style.transitionDelay = `${staggerDelay}ms`; + el.style.transitionDelay = `${staggerDelay}ms`; setTimeout(done, transitionDuration + staggerDelay); } /** - * Listener called when the enter transition has finished. - * This resets the `transitionDelay` and add one to the stagger counter. + * Finds the index of the element in the parent children subset of new elements entering the DOM. + * This is achived by filtering out the elements that are already animated, + * which are those marked with the `data-animated` attribute. * - * @param el - Element inserted. + * @param el - Element to find. + * @returns The index of the element in the parent children subset of new elements. */ - function onAfterEnter(el: Element) { - (el as HTMLElement).style.transitionDelay = '0ms'; - staggerCounter.value++; + function findAnimationIndex(el: HTMLElement) { + return [...el.parentElement!.children] + .filter(c => (c as HTMLElement).dataset.animated !== 'true') + .indexOf(el); } /** - * Listener called when the leave transition starts. - * This resets the stagger counter to 0 to init the staggered animation. + * Listener called when the enter transition has finished. + * This resets the `transitionDelay` and add mark the element as animated, + * setting the `data-animated` attribute to `true`. * - * @param _ - Element inserted. - * @param done - Callback to indicate the transition end. + * @param el - Element inserted. */ - function onLeave(_: Element, done: () => void) { - staggerCounter.value = 0; - done(); + function onAfterEnter(el: HTMLElement) { + el.style.transitionDelay = '0ms'; + el.dataset.animated = 'true'; } return { name, onEnter, - onAfterEnter, - onLeave + onAfterEnter }; } });