Presence

Contents

  1. Usage
  2. Props

Perform exit animations in Solid with Presence and Show.

<Presence>
  <Show when={toggle()}>
    <Motion animate={{ opacity: 1 }} exit={{ opacity: 0 }} />
  </Show>
</Presence>

Usage

Import Motion from "@motionone/solid" and register it with your component.

import { Component, createSignal, Show } from "solid-js";
import { Motion, Presence } from "@motionone/solid";

const App: Component = () => {
  const [toggle, setToggle] = createSignal(true);
  return (
    <div class="container">
      <Presence exitBeforeEnter>
        <Show when={toggle()}>
          <Motion.div
            initial={{ opacity: 0, scale: 0.6 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.6 }}
            transition={{ duration: 0.3 }}
          />
        </Show>
      </Presence>
      <button onClick={() => setToggle(!toggle())}>
        Toggle
      </button>
    </div>
  );
};

export default App;

Now, when a child Motion component is hidden with <Show>, it will animate to the target defined in exit prop.

Note: Presence currently only supports a single rendered child.

Animate between elements

By passing a different key to multiple children and rendering just one at a time, we can animate between them at a given time.

import { Component, createSignal } from "solid-js";
import { Motion, Presence } from "@motionone/solid";
import { Rerun } from "@solid-primitives/keyed";

const App: Component = () => {
  const [count, setCount] = createSignal(1);
  const increment = () => setCount((p) => ++p);
  return <>
    <Presence exitBeforeEnter>
      <Rerun on={count()}>
        <Motion
          initial={{ opacity: 0, x: 50 }}
          animate={{ opacity: 1, x: 0, transition: { delay: 0.05 } }}
          transition={{ duration: 0.1 }}
          exit={{ opacity: 0, x: -50 }}
        >
          {count()}
        </Motion>
      </Rerun>
    </Presence>
    <button onClick={increment}>Next</button>
  </>;
};
  
export default App;

In the above example, each element has the position: absolute CSS rule so when the incoming element is rendered it doesn't conflict with the element animating away.

In situations where this isn't possible, exitBeforeEnter={true} can be set on Presence to ensure the exiting element animates out before the entering element is rendered.

Props

initial

Default: true

If false, will disable the first animation on all child Motion elements the first time Presence is rendered.

exitBeforeEnter

Default: false

If true, Presence will wait for the exiting element to finish animating out before animating in the next one.