svelte
svelte copied to clipboard
Run transitions on initial rendering on a per-transition basis
I know that by default transitions do not run on the initial rendering (which is nice!) and that I can turn them on globally by setting intro: true
when rendering the app.
Sometimes I can be handy to have an initial transition to create emphasize, so I am wondering if there's a way to selectively turn on initial transitions on a per-transition basis.
I am thinking about something like this:
{#if visible}
<div transition:fly={{ y: -20, init: true }}>hi there!</div>
{/if}
This is not a pressing issue as it's easy to work around the approach but it'd be nice to not have to add fake state to achieve this. Right now I am doing the following or is that not necessary?
<!-- App.svelte -->
<script>
import Test from './Test.svelte';
let visible = true;
</script>
<label><input type='checkbox' bind:checked={visible}> visible</label>
<Test {visible}/>
<!-- Test.svelte -->
<script>
import { onMount } from 'svelte';
import { fly } from 'svelte/transition';
export let visible = false;
let init = false;
onMount(() => {
init = true;
});
</script>
{#if init && visible}
<div transition:fly={{ y: -20 }}>hi there!</div>
{/if}
Hi @flekschas!
Maybe it could be worth exploring if intro
could be set in the svelte:options
as well, and not just in the options given when creating a component imperatively?
<!-- Test.svelte -->
<svelte:options intro />
<div transition:fly={{ y: -20 }}>hi there!</div>
That would also work but it still means that all transitions within that component run on the initial rendering right?
I guess maybe a with my proposal problem is that the transition object doesn't know about the intro
transitioning unless svelte triggers it. I tried to find out where (in the code) Svelte decides to trigger a transition on the initial render or not but I could find the location yet. I'll have to do some more digging to find out more how my proposal could be achieved.
I don't think we should be instructing the compiler by passing options into a runtime function (which is what the parameters of an animation or transition directive are).
If this is something that we want to support then it needs to be a directive modifier, just like local
is. It would look like:
<div transition:fly|intro={ params } />
<!-- Test.svelte --> <script> import { onMount } from 'svelte'; import { fly } from 'svelte/transition'; export let visible = false; let init = false; onMount(() => { init = true; }); </script> {#if init && visible} <div transition:fly={{ y: -20 }}>hi there!</div> {/if}
As someone who works on a lot of animation heavy projects, boilerplate like this is often littered all over codebases.
I would absolutely adore an |intro
option!!
As someone who deals with it everyday, I would be down to take a swing at an implementation. I'll probably need a push in the right direction, but I'd love to help progress this forward!
Any progress regarding this? Definitly it would make my life easier
@FractalHQ did you find any workaround? I also spent a lot of time to write similiar boilerplate…
@niklasgrewe Not exactly. I've been using this component to reduce the amount of boilerplate a bit. I can type <OnM
and tab to auto import and auto complete, sticking any transition stuff inside. Works for me.
I tried the fratils library and it provides a nice little abstraction for OnMount, which (sort of) solves the problem, but the animation doesn't play as smoothly. At the end, it kind of snaps into place. I would love the equivalent of intro: true
for the declarative code.
I came across this issue today and just wanted to put in a +1 for the |intro param idea. Seems like a clean enough fix for this behavior.
This feature is definitely needed. Using the onMount method often times makes the animation look blocky and not smooth