+ {#each todos.filter(t => !t.done) as todo (todo.id)}
+
+ {/each}
+
+
+
+
done
+ {#each todos.filter(t => t.done) as todo (todo.id)}
+
+ {/each}
+
+
+
-
-
-
-
-
-
todo
- {#each todos.filter(t => !t.done) as todo (todo.id)}
-
- {/each}
-
-
-
-
done
- {#each todos.filter(t => t.done) as todo (todo.id)}
-
- {/each}
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/crossfade.js b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/crossfade.js
deleted file mode 100644
index e11e18b60e..0000000000
--- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/crossfade.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { quintOut } from 'svelte/easing';
-
-export default function crossfade({ send, receive, fallback }) {
- let requested = new Map();
- let provided = new Map();
-
- function crossfade(from, node) {
- const to = node.getBoundingClientRect();
- const dx = from.left - to.left;
- const dy = from.top - to.top;
-
- const style = getComputedStyle(node);
- const transform = style.transform === 'none' ? '' : style.transform;
-
- return {
- duration: 400,
- easing: quintOut,
- css: (t, u) => `
- opacity: ${t};
- transform: ${transform} translate(${u * dx}px,${u * dy}px);
- `
- };
- }
-
- return {
- send(node, params) {
- provided.set(params.key, {
- rect: node.getBoundingClientRect()
- });
-
- return () => {
- if (requested.has(params.key)) {
- const { rect } = requested.get(params.key);
- requested.delete(params.key);
-
- return crossfade(rect, node);
- }
-
- // if the node is disappearing altogether
- // (i.e. wasn't claimed by the other list)
- // then we need to supply an outro
- provided.delete(params.key);
- return fallback(node, params);
- };
- },
-
- receive(node, params) {
- requested.set(params.key, {
- rect: node.getBoundingClientRect()
- });
-
- return () => {
- if (provided.has(params.key)) {
- const { rect } = provided.get(params.key);
- provided.delete(params.key);
-
- return crossfade(rect, node);
- }
-
- requested.delete(params.key);
- return fallback(node, params);
- };
- }
- };
-}
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte
index c46096c204..3cb21a8ed9 100644
--- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte
+++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte
@@ -1,8 +1,10 @@
-
-
-
-
-
-
-
todo
- {#each todos.filter(t => !t.done) as todo (todo.id)}
-
- {/each}
-
-
-
-
done
- {#each todos.filter(t => t.done) as todo (todo.id)}
-
- {/each}
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/crossfade.js b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/crossfade.js
deleted file mode 100644
index e11e18b60e..0000000000
--- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/crossfade.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import { quintOut } from 'svelte/easing';
-
-export default function crossfade({ send, receive, fallback }) {
- let requested = new Map();
- let provided = new Map();
-
- function crossfade(from, node) {
- const to = node.getBoundingClientRect();
- const dx = from.left - to.left;
- const dy = from.top - to.top;
-
- const style = getComputedStyle(node);
- const transform = style.transform === 'none' ? '' : style.transform;
-
- return {
- duration: 400,
- easing: quintOut,
- css: (t, u) => `
- opacity: ${t};
- transform: ${transform} translate(${u * dx}px,${u * dy}px);
- `
- };
- }
-
- return {
- send(node, params) {
- provided.set(params.key, {
- rect: node.getBoundingClientRect()
- });
-
- return () => {
- if (requested.has(params.key)) {
- const { rect } = requested.get(params.key);
- requested.delete(params.key);
-
- return crossfade(rect, node);
- }
-
- // if the node is disappearing altogether
- // (i.e. wasn't claimed by the other list)
- // then we need to supply an outro
- provided.delete(params.key);
- return fallback(node, params);
- };
- },
-
- receive(node, params) {
- requested.set(params.key, {
- rect: node.getBoundingClientRect()
- });
-
- return () => {
- if (provided.has(params.key)) {
- const { rect } = provided.get(params.key);
- provided.delete(params.key);
-
- return crossfade(rect, node);
- }
-
- requested.delete(params.key);
- return fallback(node, params);
- };
- }
- };
-}
\ No newline at end of file
diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/text.md b/site/content/tutorial/10-transitions/08-deferred-transitions/text.md
index e649762f57..49f626554d 100644
--- a/site/content/tutorial/10-transitions/08-deferred-transitions/text.md
+++ b/site/content/tutorial/10-transitions/08-deferred-transitions/text.md
@@ -4,4 +4,27 @@ title: Deferred transitions
A particularly powerful feature of Svelte's transition engine is the ability to *defer* transitions, so that they can be coordinated between multiple elements.
-TODO https://github.com/sveltejs/svelte/issues/2159
\ No newline at end of file
+Take this pair of todo lists, in which toggling a todo sends it to the opposite list. In the real world, objects don't behave like that — instead of disappearing and reappearing in another place, they move through a series of intermediate positions. Using motion can go a long way towards helping users understand what's happening in your app.
+
+We can achieve this effect using the `crossfade` function, which creates a pair of transitions called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used.
+
+Find the `