I'm writing a small app using Svelte that presents a list of collapsible panels with text to the user, has them select a set of those panels, and, when the user clicks a button, groups these panels into another collapsible panel in a different list. Conceptually, it's the deferred transitions tutorial with an extra layer on one end.
I have prepared a REPL so you can follow along. Replace the component in App.svelte
to switch the implementations.
The Original.svelte
component illustrates the problem:
I'm using Svelte's crossfade
transition to send and receive, and everything looks great when the grouped panels are collapsed. Any open panel, however, will warp awkwardly to its closed state when sent between the lists, which I understand is an effect of crossfade
. The solution is obvious: close the panels first, then send them over to their target.
My question is, now, what is the idiomatic/optimal way to do that in Svelte?
The WithDelay.svelte
component shows my attempt using delay
on the individual panel transitions based on whether a panel was open. As is evident, this delays the send/receive transitions but still warps the panels, no matter how long the delay is (try a second or longer).
My second intuition was to collect the panels to be moved in an intermediate list, close them, and finally use the transition events on:outrostart
/on:outroend
to finalize the move. However, the logic was too lengthy to be correct, requiring multiple helper functions and extra arrays to track the elements. Once multiple panels had their events fire simultaneously, everything just went haywire. Preventing race conditions turned out so complicated that I scrapped that attempt entirely.
My third attempt can be seen in WithTimeout.svelte
, where I resorted to using setTimeout
to delay the actual moving of elements after the panels have been closed. As expected, that works exactly how it should and should be used as a reference for what I want to achieve, but using setTimeout
just feels wrong. Still, I feel like I should not need to implement my own wait
function using requestAnimationFrame
since Svelte itself seems to have no built-in function for that. Internally, it runs the transition in a loop construct that uses requestAnimationFrame
.
I'd go on with the timeout, but I would like to hear more experienced opinions before proceeding. I'm not even sure if my concerns are even justified. Maybe requestAnimationFrame
only matters when doing actual transition stuff, and setTimeout
is fine for assigning variables? Thanks a lot for your help!