Pier
Pier

Reputation: 10837

How to define a conditional transition in Svelte?

In Svelte we can add transitions with:

<div in:fade={{duration: 150}}>...</div>

It's also possible to have conditional HTML attributes with:

<input disabled={null}>

This doesn't work with transitions:

<div in:fade={null}>...</div>

Which throws this error as it expects a config object:

Cannot read property 'delay' of null

So what would would be the appropriate way of adding a conditional transition in Svelte?

Other than:

{#if animate}
    <div in:fade></div>
{:else}
    <div></div>
{/if}

Upvotes: 23

Views: 5280

Answers (3)

Andrew Childs
Andrew Childs

Reputation: 2985

You could also solve this with a wrapper around the transition function. Demo here.

<script>
  import { fly, slide } from 'svelte/transition';
    
  export let animate = true;
    
  function maybe(node, options) {
    if (animate) {
      return options.fn(node, options);
    }
  }
</script>

<h1 in:maybe={{ fn: fly, x: 50 }} out:maybe={{ fn: slide }}>Hello!</h1>

Upvotes: 15

Andrei Savin
Andrei Savin

Reputation: 2484

The accepted answer is not quite correct. Imagine you have a notification alert with a transition within a modal with a different transition. You want to prevent the alert's transition from firing when the modal closes. Now you have this situation:

<!-- Modal.svelte -->
<div class="modal" transition:fade={{ duration: 500 }}>
  <div class="alert" transition:slide={{ duration: 0 }}>
    Alert!
  </div>
</div>

The alert immediately disappears while the modal slowly fades away.

Instead, I suggest to create a wrapper component that you can re-use in those situations:

<!-- Transition.svelte -->
<script lang="ts">
  import { slide } from 'svelte/transition';

  export let transition: boolean = true;
  export let duration: number = 500;
</script>

{#if transition}
  <div transition:slide={{ duration }}>
    <slot />
  </div>
{:else}
  <slot />
{/if}
<!-- Modal.svelte -->
<div class="modal" transition:fade={{ duration: 500 }}>
  <Transition transition={false}>
    <div class="alert">
      Alert!
    </div>
  </Transition>
</div>

Upvotes: 2

Stephane Vanraes
Stephane Vanraes

Reputation: 16451

You can pass in a configuration object to the transition with a duration of 0 (effectively instantaneously):

<script>
    import { fade } from 'svelte/transition'
    
    export let animate
</script>

<div in:fade={{ duration: animate ? 500 : 0 }}>
    ...
</div>

Upvotes: 17

Related Questions