motion-sv

SKILL.md

Motion for Svelte (motion-sv)

A port of the Motion library (formerly Framer Motion) specifically for Svelte 5. It aligns closely with the motion-v API structure rather than the React version.

Stack Requirements

  • MUST be used with Svelte 5 (Runes).
  • Package name: motion-sv.

Core Components

motion

The primary component factory. Use dot notation to render any HTML element.

<script>
  import { motion } from "motion-sv";
</script>

<!-- Sections & Headings -->
<motion.section initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
  <motion.h1 animate={{ y: 0 }}>Headline</motion.h1>
</motion.section>

<!-- Links & Buttons -->
<motion.a
  href="/about"
  whileHover={{ scale: 1.05 }}
  whilePress={{ scale: 0.95 }}
>
  Go to About
</motion.a>

Styling Pattern (Important)

ALWAYS pass styles as an object via style={{ key: value }}, never as a string. This is required to bind MotionValues correctly without triggering re-renders.

<script>
  import { motion, useMotionValue } from "motion-sv";
  const x = useMotionValue(0);
</script>

<!-- ❌ BAD: String syntax (Values won't update) -->
<motion.div style="background-color: red; transform: translateX(10px)" />

<!-- ✅ GOOD: Object syntax -->
<motion.div
  style={{
    x,
    backgroundColor: "#ff0000",
    "--custom-var": 100,
  }}
/>

Type Safety & Variants

For better developer experience and type safety, define variants using the Variants type.

<script lang="ts">
  import { motion, type Variants } from "motion-sv";

  const boxVariants: Variants = {
    hidden: { opacity: 0, scale: 0.8 },
    visible: {
      opacity: 1,
      scale: 1,
      transition: { duration: 0.5 },
    },
  };
</script>

<motion.div variants={boxVariants} initial="hidden" animate="visible" />

Supported Props

  • Animation: initial, animate, exit, transition, variants.
  • Gestures: whileHover, whilePress (preferred over whileTap), whileDrag, whileFocus.
  • Drag: drag (boolean | "x" | "y"), dragConstraints, dragElastic, dragMomentum.
  • Events: onAnimationStart, onAnimationComplete, onUpdate.
  • Gesture Events: onHoverStart, onHoverEnd, onPress, onPressStart, onPressEnd.

Viewport / Scroll Animations (Vue API Style)

Important: Use inViewOptions instead of the React viewport prop.

<motion.section
  initial={{ opacity: 0 }}
  whileInView={{ opacity: 1 }}
  inViewOptions={{
    once: true,
    amount: "some", // "some" | "all" | 0..1
    margin: "0px 0px -200px 0px",
  }}
>
  Hello
</motion.section>

AnimatePresence

Enables exit animations. Modes: "sync" (default), "wait", "popLayout".

<script>
  import { motion, AnimatePresence } from "motion-sv";
  let show = $state(true);
</script>

<AnimatePresence mode="wait">
  {#if show}
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      key="unique-key"
    />
  {/if}
</AnimatePresence>

Layout Animations (CRITICAL DIFFERENCE)

Svelte lacks getSnapshotBeforeUpdate. You MUST use createLayoutMotion for layout animations.

Pattern:

  1. Create a proxy object: const layout = createLayoutMotion(motion).
  2. Use <layout.div> instead of <motion.div>.
  3. Wrap state updates with layout.update.with(fn).
<script>
  import { motion, createLayoutMotion } from "motion-sv";

  let isOn = $state(false);
  const layout = createLayoutMotion(motion);

  // Wrap state mutation
  const toggle = layout.update.with(() => (isOn = !isOn));
</script>

<div onclick={toggle}>
  <!-- Use layout.div and layoutDependency or layoutId -->
  <layout.div
    layoutDependency={isOn}
    transition={{ type: "spring", stiffness: 700, damping: 30 }}
  />
</div>

Reorder (Drag & Drop Lists)

Use specific components for reordering lists.

<script>
  import { ReorderGroup, ReorderItem } from "motion-sv";
  let items = $state([0, 1, 2]);
</script>

<ReorderGroup axis="y" bind:values={items}>
  {#each items as item (item)}
    <ReorderItem value={item}>
      {item}
    </ReorderItem>
  {/each}
</ReorderGroup>

Performance (Lazy Motion)

Reduce bundle size by loading features on demand.

<script>
  import { LazyMotion, domAnimation } from "motion-sv";
</script>

<LazyMotion features={domAnimation}>
  <!-- Children using motion components -->
</LazyMotion>

Best Practices

  • API Alignment: Follow motion-v prop naming (e.g., inViewOptions, whilePress).
  • Directives: Do NOT use Svelte's transition:fn.
  • Styles: Always use the object syntax style={{ ... }}.
Weekly Installs
5
GitHub Stars
111
First Seen
11 days ago
Installed on
gemini-cli5
github-copilot5
codex5
amp5
cline5
kimi-cli5