Because Svelte lacks the lifecycle hooks used by Framer Motion (like getSnapshotBeforeUpdate), layout animations in motion-sv require a helper to track state changes and trigger layout updates.
Use createLayoutMotion to obtain a layout controller that provides two ways to signal updates:
layout.update(): Manually mark a layout change after a state update.layout.update.with(fn): A wrapper that automatically tracks the state update inside the provided function.
When using layout components, use the layoutDependency prop to provide a reactive trigger if the element is not being remounted.
<script lang="ts">
import { motion, createLayoutMotion } from "motion-sv";
let isOn = $state(false);
const layout = createLayoutMotion();
// Option 1: Automatic tracking via wrapper
const toggle = layout.update.with(() => (isOn = !isOn));
// Option 2: Manual update
/*
function toggle() {
isOn = !isOn;
layout.update();
}
*/
</script>
<motion.button style={{ justifyContent: "flex-" + (isOn ? "start" : "end") }} onclick={toggle}>
<layout.div
style={handle}
layoutDependency={isOn}
transition={{ type: "spring", visualDuration: 0.2, bounce: 0.2 }}
/>
</motion.button>