fix: Abort outro when intro starts (#12321)

Fixes #12319

---------

Co-authored-by: Leon Scherer <info@leonscherer.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
pull/12395/head
Leon Scherer 4 months ago committed by GitHub
parent 95422e22b6
commit fd7b950e7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: abort outro when intro starts

@ -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?.();
}
},

@ -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,
`
<div style="opacity: 0.75;">a</div>
<div style="opacity: 0.75;">a</div>
`
);
// 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
`
<div style="">a</div>
<div style="opacity: 0.25;">b</div>
<div style="opacity: 0.25;">c</div>
<div style="">a</div>
<div style="opacity: 0.25;">b</div>
<div style="opacity: 0.25;">c</div>
`
);
// intros of new items almost finished, aborted outro shouldn't overlap re-intro
raf.tick(75);
assert.htmlEqual(
target.innerHTML,
`
<div>a</div>
<div>b</div>
<div>c</div>
<div style="">a</div>
<div style="opacity: 0.5;">b</div>
<div style="opacity: 0.5;">c</div>
<div>a</div>
<div>b</div>
<div>c</div>
<div style="">a</div>
<div style="opacity: 0.5;">b</div>
<div style="opacity: 0.5;">c</div>
`
);
}

@ -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}`
};
}
</script>
{#if visible}
{#each array as item}
<div transition:slide={{duration:100}}>{item}</div>
<div transition:slide|global>{item}</div>
{/each}
{/if}
{#if !visible}
{:else}
{#if !visible}{:else}
{#each array as item}
<div transition:slide={{duration:100}}>{item}</div>
<div transition:slide|global>{item}</div>
{/each}
{/if}
Loading…
Cancel
Save