Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rapidly toggling element with out: transition causes incorrect node removal #13681

Closed
kurmachu opened this issue Oct 18, 2024 · 4 comments · Fixed by #13884
Closed

Rapidly toggling element with out: transition causes incorrect node removal #13681

kurmachu opened this issue Oct 18, 2024 · 4 comments · Fixed by #13884

Comments

@kurmachu
Copy link

Describe the bug

When an element with a seperate in: and out: transition (or just an out: transition) is rapidly toggled in a short period (as in, hidden due to state-based {#if condition} being briefly false, and then shown due to being true), it is incorrectly removed from the document after the intro animation finishes. If there is no in:, the outro animation plays instead and the element is hidden, despite the {#if ...} being true.

I've run into this when attempting to handle Form Actions from SvelteKit, with something like {#if form?.error}. If the form is re-submitted this becomes undefined before quickly becoming a value, casing the issue on the element presenting the error.

Reproduction

A REPL which attempts to simulate the issue artificially using timeouts on state:
https://svelte-5-preview.vercel.app/#H4sIAAAAAAAACo1QwW7bMAz9FUIr0BhI6-3qOSoG7BN6m3ZwJDolIlOqRKcIDP37IDXYeusOgkTyPfG9t6mZPGY1_NoUTwuqQf2IUe2VXGMt8gW9oNqrHNZka2fMNlEUbdgILTEkgQ3mySEUmFNY4P6d00uaOJNQ4PuKrcejQIjIcIC7LJPgbp58xu674Tq-I84RrewqpjM89v928faF5kYuFTo6ukCWq8eDUcfJnk8prOwebPAhDZDQGQXEQxMWVmmPptnIGLW8UAbKIOF08jgdPYINLMgy9rHBxt7RRRveeprrRh6Pq0hgCGw92fNh23UHvd3cSFqxFF2rsX8H6k8ozXkp2vqQ8VNSlfRG7MLbY0Z5pgXDKru_IyMff62dsoev3f-yqvwb6VtnuBT9upI9--stoI_yov5Zo38Jq3dwxAGaoScwqt5GwQBGNVPOqFLjVHu1BEczoVNDS-p3-QOlBZh6eAIAAA==

Press "quickly toggle" twice to see the issue.
You can also remove in:fade to see how just an outro behaves.

Logs

No response

System Info

System:
    OS: Windows 11 10.0.22635
    CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
    Memory: 20.63 GB / 31.87 GB
  Binaries:
    Node: 22.9.0 - C:\Program Files\nodejs\node.EXE
    npm: 10.7.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (127.0.2651.8)
  npmPackages:
    svelte: ^5.0.0-next.1 => 5.0.0-next.269

Severity

annoyance

@adiguba
Copy link
Contributor

adiguba commented Oct 19, 2024

Hello,

It seems that the problem come from these lines :

// create a dummy animation that lasts as long as the delay (but with whatever devtools
// multiplier is in effect). in the common case that it is `0`, we keep it anyway so that
// the CSS keyframes aren't created until the DOM is updated
var animation = element.animate(keyframes, { duration: delay });
animation.onfinish = () => {

=> The dummy animation with a delay of 0 instantly gets the 'finished' status.
But for some reason unknown to me, in this case the onfinish() handler may be executed after a cancel().

I managed to reproduce the scenario in this REPL : the onfinish() is called even if the animation is cancelled before !

Adding this line at the beginning of onfinish() seem to fix the bug :

		if (animation.playState === 'idle') return;

But I don't known if this is enough, neither how to create a test for this !

@kurmachu
Copy link
Author

Another solution could be to use a small but non-zeo delay, like out:fade={{delay:0.00001}}

Sadly this doesn't work entirely consistently.
It does help a lot though, so I'll use it as a temporary fix to continue developing; thank you!
Tested on Android with Chrome Beta 131.0.6778.2

@adiguba
Copy link
Contributor

adiguba commented Oct 19, 2024

Oh it's work on Firefox but not Chrome.
The latter seems to need a delay of 0.001 instead of 0.00001...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants