Skip to main content

In the previous chapter, we used deferred transitions to create the illusion of motion as elements move from one todo list to the other.

To complete the illusion, we also need to apply motion to the elements that aren't transitioning. For this, we use the animate directive.

First, import the flip function — flip stands for 'First, Last, Invert, Play' — from svelte/animate into TodoList.svelte:

TodoList.svelte
<script>
	import { flip } from 'svelte/animate';
	import { send, receive } from './transition.js';

	export let store;
	export let done;
</script>

Then add it to the <li> elements:

TodoList.svelte
<li
	class:done
	in:receive={{ key: todo.id }}
	out:send={{ key: todo.id }}
	animate:flip
>

The movement is a little slow in this case, so we can add a duration parameter:

TodoList.svelte
<li
	class:done
	in:receive={{ key: todo.id }}
	out:send={{ key: todo.id }}
	animate:flip={{ duration: 200 }}
>

duration can also be a d => milliseconds function, where d is the number of pixels the element has to travel

Note that all the transitions and animations are being applied with CSS, rather than JavaScript, meaning they won't block (or be blocked by) the main thread.

Next: Actions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<script>
	import { send, receive } from './transition.js';
 
	export let store;
	export let done;
</script>
 
<ul class="todos">
	{#each $store.filter((todo) => todo.done === done) as todo (todo.id)}
		<li
			class:done
			in:receive={{ key: todo.id }}
			out:send={{ key: todo.id }}
		>
			<label>
				<input
					type="checkbox"
					checked={todo.done}
					on:change={(e) => store.mark(todo, e.currentTarget.checked)}
				/>
 
				<span>{todo.description}</span>
 
				<button on:click={() => store.remove(todo)} aria-label="Remove"></button>
			</label>
		</li>
	{/each}
</ul>
 
<style>
	label {
		width: 100%;
		height: 100%;
		display: flex;
	}
 
	span {
		flex: 1;
	}
 
	button {
		background-image: url(./remove.svg);
	}
</style>
initialising