Home/Docs/Crossfade
Transitions

Crossfade

crossfade() returns a [send, receive] pair. Put out="send({ key })" on an element leaving one spot and in="receive({ key })" on the element entering another with the same key, and the two animate as one element flying between the positions. When a key has no partner (an item that just disappears), the fallback transition plays instead.

Define the pair in <script>. Because crossfade is destructured, wrap the two functions as named consts so they're callable from the template:

Component.html
<script>
  import { crossfade, transitions } from "olum";

  const _cf = crossfade({ duration: 300, fallback: transitions.scale });
  const send = (node, params) => _cf[0](node, params);
  const receive = (node, params) => _cf[1](node, params);

  const state = { todos: [/* … */] };
  const done = () => state.todos.filter((t) => t.done);
  const active = () => state.todos.filter((t) => !t.done);
</script>

<for each="todo of active()" key="todo.id">
  <transition in="receive({ key: todo.id })" out="send({ key: todo.id })" flip>
    <li>{todo.text}</li>
  </transition>
</for>
<!-- a matching list of done() items with the same in/out/flip -->

crossfade({ duration?, easing?, fallback? })easing is a name string; fallback is any transition function (e.g. a built-in from the transitions import, or your own). It composes with flip so the remaining items slide into the gap.

Key off a primitive, not an object. State is deeply reactive, so state.selected !== someItem (object identity) won't behave as you expect — compare an id (state.selectedId !== item.id) and use that id as the crossfade key.