From fd7b950e7de4c1a4ff7ae9c12f3d42b5ea63c864 Mon Sep 17 00:00:00 2001 From: Leon Scherer <55341374+Fruup@users.noreply.github.com> Date: Thu, 11 Jul 2024 12:48:06 +0200 Subject: [PATCH] fix: Abort outro when intro starts (#12321) Fixes #12319 --------- Co-authored-by: Leon Scherer Co-authored-by: Simon Holthausen --- .changeset/bright-needles-pretend.md | 5 +++ .../client/dom/elements/transitions.js | 4 +- .../samples/transition-abort/_config.js | 40 +++++++++++++++---- .../samples/transition-abort/main.svelte | 16 ++++---- 4 files changed, 49 insertions(+), 16 deletions(-) create mode 100644 .changeset/bright-needles-pretend.md diff --git a/.changeset/bright-needles-pretend.md b/.changeset/bright-needles-pretend.md new file mode 100644 index 0000000000..03bb20e4f1 --- /dev/null +++ b/.changeset/bright-needles-pretend.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: abort outro when intro starts diff --git a/packages/svelte/src/internal/client/dom/elements/transitions.js b/packages/svelte/src/internal/client/dom/elements/transitions.js index c2fbeface1..cc96692881 100644 --- a/packages/svelte/src/internal/client/dom/elements/transitions.js +++ b/packages/svelte/src/internal/client/dom/elements/transitions.js @@ -190,6 +190,9 @@ export function transition(flags, element, get_fn, get_params) { in() { element.inert = inert; + // abort the outro to prevent overlap with the intro + outro?.abort(); + if (is_intro) { dispatch_event(element, 'introstart'); intro = animate(element, get_options(), outro, 1, () => { @@ -197,7 +200,6 @@ export function transition(flags, element, get_fn, get_params) { intro = current_options = undefined; }); } else { - outro?.abort(); reset?.(); } }, diff --git a/packages/svelte/tests/runtime-legacy/samples/transition-abort/_config.js b/packages/svelte/tests/runtime-legacy/samples/transition-abort/_config.js index 5072e9fa19..e35b08f2a8 100644 --- a/packages/svelte/tests/runtime-legacy/samples/transition-abort/_config.js +++ b/packages/svelte/tests/runtime-legacy/samples/transition-abort/_config.js @@ -12,24 +12,48 @@ export default test({ async test({ assert, component, target, raf }) { component.visible = false; - // abort halfway through the outro transition - raf.tick(50); + raf.tick(25); + assert.htmlEqual( + target.innerHTML, + ` +
a
+
a
+ ` + ); + // abort 1/4 through the outro transition await component.$set({ visible: true, array: ['a', 'b', 'c'] }); + raf.tick(50); + assert.htmlEqual( + target.innerHTML, + // because outro is aborted it will be finished earlier with the intro than the new items + ` +
a
+
b
+
c
+ +
a
+
b
+
c
+ ` + ); + + // intros of new items almost finished, aborted outro shouldn't overlap re-intro + raf.tick(75); assert.htmlEqual( target.innerHTML, ` -
a
-
b
-
c
+
a
+
b
+
c
-
a
-
b
-
c
+
a
+
b
+
c
` ); } diff --git a/packages/svelte/tests/runtime-legacy/samples/transition-abort/main.svelte b/packages/svelte/tests/runtime-legacy/samples/transition-abort/main.svelte index b574229712..1fbfa13685 100644 --- a/packages/svelte/tests/runtime-legacy/samples/transition-abort/main.svelte +++ b/packages/svelte/tests/runtime-legacy/samples/transition-abort/main.svelte @@ -2,20 +2,22 @@ export let array = ['a']; export let visible = true; - function slide(_, params) { - return params; + function slide(_) { + return { + duration: 100, + css: (t) => `opacity: ${t}` + }; } {#if visible} {#each array as item} -
{item}
+
{item}
{/each} {/if} -{#if !visible} -{:else} +{#if !visible}{:else} {#each array as item} -
{item}
+
{item}
{/each} -{/if} \ No newline at end of file +{/if}