Variants
A variant is a named target. An element lists them in variants, and initial, animate, exit and the while* props name one. Its children with variants of their own follow the same names, each with its own target, spaced out by the parent's transition.
import { stagger, w } from "@wardic/solid/unstable/v2"
import { createSignal, For } from "solid-js"
const ITEMS = ["Vases", "Bowls", "Plates", "Jugs"]
// The list names a variant; each item follows it with its own target. The list's transition spaces
// them out: in from the first, out from the last.
const list = {
open: { transition: { delayChildren: stagger(0.07) } },
closed: { transition: { delayChildren: stagger(0.05, { from: "last" }) } },
}
const item = {
open: { opacity: 1, x: 0 },
closed: { opacity: 0, x: -24 },
}
export default function Variants() {
const [open, setOpen] = createSignal(true)
return (
<div class="sample-stack">
<button class="sample-button" onClick={() => setOpen(!open())}>
{open() ? "Close" : "Open"}
</button>
<w.ul class="sample-list" variants={list} initial="closed" animate={open() ? "open" : "closed"}>
<For each={ITEMS}>{(name) => <w.li class="sample-item" variants={item}>{name}</w.li>}</For>
</w.ul>
</div>
)
}import { stagger, w } from "@wardic/solid"
import { createSignal, For } from "solid-js"
const ITEMS = ["Vases", "Bowls", "Plates", "Jugs"]
// The list names a variant; each item follows it with its own target. The list's transition spaces
// them out: in from the first, out from the last.
const list = {
open: { transition: { delayChildren: stagger(0.07) } },
closed: { transition: { delayChildren: stagger(0.05, { from: "last" }) } },
}
const item = {
open: { opacity: 1, x: 0 },
closed: { opacity: 0, x: -24 },
}
export default function Variants() {
const [open, setOpen] = createSignal(true)
return (
<div class="sample-stack">
<button class="sample-button" onClick={() => setOpen(!open())}>
{open() ? "Close" : "Open"}
</button>
<w.ul class="sample-list" variants={list} initial="closed" animate={open() ? "open" : "closed"}>
<For each={ITEMS}>{(name) => <w.li class="sample-item" variants={item}>{name}</w.li>}</For>
</w.ul>
</div>
)
}import { motion, stagger } from "motion/react"
import { useState } from "react"
const ITEMS = ["Vases", "Bowls", "Plates", "Jugs"]
// The list names a variant; each item follows it with its own target. The list's transition spaces
// them out: in from the first, out from the last.
const list = {
open: { transition: { delayChildren: stagger(0.07) } },
closed: { transition: { delayChildren: stagger(0.05, { from: "last" }) } },
}
const item = {
open: { opacity: 1, x: 0 },
closed: { opacity: 0, x: -24 },
}
export default function Variants() {
const [open, setOpen] = useState(true)
return (
<div className="sample-stack">
<button className="sample-button" onClick={() => setOpen(!open)}>
{open ? "Close" : "Open"}
</button>
<motion.ul className="sample-list" variants={list} initial="closed" animate={open ? "open" : "closed"}>
{ITEMS.map((name) => (
<motion.li key={name} className="sample-item" variants={item}>
{name}
</motion.li>
))}
</motion.ul>
</div>
)
}Children follow
A child with variants and no initial or animate of its own starts from its parent's initial and follows its animate. On a server-rendered page, every child arrives at its initial already, so the entrance starts from there with no flash. An element in between, without variants, passes the names through; inherit={false} keeps a child out.
Orchestration
The parent's transition times its children:
staggerChildren: 0.05starts each child 50 ms after the one before.delayChildrenwaits before the first, or withstagger(0.07, { from, startDelay, ease }), decides each child's whole delay:from: "last"runs them back to front.when: "beforeChildren"or"afterChildren"runs the parent's own animation first or last.
Custom, and lists of names
A variant can be a function of custom, so each child computes its own target:
const item = { open: (i: number) => ({ opacity: 1, transition: { delay: i * 0.1 } }) }
<w.li variants={item} custom={index()} />animate={["visible", "active"]} names more than one: they merge in order. And a gesture can name a variant too, whileHover="hover", which the children follow as they follow animate.