Jordan
Jordan

Reputation: 431

Can svelte transition be conditional?

Is it possible to add a condition to a svelte transition in the html element

<script>
let visible = true;
</script>
{#if visible}
    <p
        transition:fly="{{ y: 200, duration: 2000 }}"
    >
        Flies in and out
    </p>
{/if}

like idk something like

<script>
let visible = true;
let iWantFly = true
</script>

{#if visible}
    <p
        transition:fly:iWantFly="{{ y: 200, duration: 2000 }}"
    >
        Flies in and out
    </p>
{/if}

or even like

<script>
let visible = true;
let flyType = 'sureThing'
</script>

{#if visible}
    <p
        transition:fly:{flyType === 'sureThing'}="{{ y: 200, duration: 2000 }}"
    >
        Flies in and out
    </p>
{/if}

I know could do two separate elements like

<script>
let visible = true;
let baseEl;
let flyType = 'sureThing'
</script>

{#if visible && flyType === 'sureThing'}
    <p
        bind:this={baseEl}
        transition:fly="{{ y: 200, duration: 2000 }}"
    >
        Flies in and out
    </p>
{/if}
{#if visible && flyType === 'otherThing'}
    <p bind:this={baseEl}>
        Flies in and out
    </p>
{/if}
{#if visible && flyType === 'thisThing'}
    <p 
      bind:this={baseEl}
      transition:fade
    >
        Flies in and out
    </p>
{/if}

but problem is one that's duplicating code and two I'm trying to bind to the element so flipping between 'flyType' switches to a new element and screws up the bind. Or would I need to make. custom one? I'm new so haven't done that yet but don't want to overcomplicate it

Responding to formerly marked correct answer appears not to work Using example from @geoffrich when starting in a 'no' string and toggling to a yes then visible the transition moves instantly

<script>
import { fly } from 'svelte/transition';
    let visible = true;
    let shouldTransition = 'no';
    function toggleTransition(){
      shouldTransition = shouldTransition === 'yes' ? 'no' : 'yes';
    }
</script>
<label><input type='checkbox' bind:checked={visible}> Visible</label>
      <button on:click={toggleTransition}>toggleTransition: {shouldTransition}</button>

{#if visible}
  <p transition:transitionToUse={{ y: 200, duration: 500 }}>Flies in and out</p>
{/if}

Upvotes: 2

Views: 1270

Answers (2)

Jordan
Jordan

Reputation: 431

I just made a custom transition that works

<script>
import { fly } from 'svelte/transition';
import { cubicOut } from 'svelte/easing';
function myFly(node, { y, duration }) {
        return {
            duration,
            css: (t, u) => {
        if(shouldTransition === 'yes'){
          const eased = cubicOut(u);
          return `
            transform: translateY(${eased * y}px);
          `
        } else {
          return null
        }
                
            }
        };
    }
    let visible = true;
    let shouldTransition = 'no';
    function toggleTransition(){
      shouldTransition = shouldTransition === 'yes' ? 'no' : 'yes';
    }
</script>
<label><input type='checkbox' bind:checked={visible}> Visible</label>
      <button on:click={toggleTransition}>toggleTransition: {shouldTransition}</button>

      {#if visible}
      <p transition:myFly={{ y: 200, duration: 500 }}>Flies in and out</p>
      {/if}

Update I actually think that might not work because the duration still occurs for each but I found using in and out transition even though for same transition function that worked. This was my final code

<script>
function myFly(node, { y, duration }) {
  return (typeToUse === 'full') ? {
    duration,
    css: (t, u) => {
      const eased = cubicOut(u);
      return `transform: translateY(${eased * y}px);`
    }
  } : null;
}
</script>
<p 
in:myFly={{ y: windowHeight, duration: 600 }}
      out:myFly={{ y: windowHeight, duration: 600 }} >test</p>

Upvotes: 0

Geoff Rich
Geoff Rich

Reputation: 5492

A Svelte transition is just a function, so you can reactively change which function to use for the transition. Here's an example:

<script>
    import { fly } from 'svelte/transition';
    let visible = true;
    let shouldTransition = true;
    
    // if shouldTransition is false, use a transition function that does nothing
    $: transitionToUse = shouldTransition ? fly : () => {};
</script>

<label><input type='checkbox' bind:checked={visible}> Visible</label>
<label><input type='checkbox' bind:checked={shouldTransition}> Enable transition</label>

{#if visible}
<p transition:transitionToUse={{ y: 200, duration: 500 }}>Flies in and out</p>
{/if}

Upvotes: 2

Related Questions