All skills

Use when adding animations with Motion Vue (motion-v) - provides motion component API, gesture animations, scroll-linked effects, layout transitions, and composables for Vue 3/Nuxt

  • 4 files
  • 20.8 KB
  • MIT
  • Updated 8 months ago
  • GitHub

Use this Skill: https://skilld.dev/gh/onmax/claude-config/motion

This session only. Nothing lands on disk.

referencescomponents.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Motion Component API

Import Patterns

motion (lowercase) - Standard pattern

The standard way to use motion-v with dot notation:

<script setup>
import { motion } from 'motion-v'
</script>

<template>
  <motion.div />
</template>

Motion (capital) - Primitive pattern

Alternative pattern using as prop. Useful when element type needs to be dynamic at runtime:

<script setup>
import { Motion } from 'motion-v'
</script>

<template>
  <Motion as="div" />
</template>

Use motion (lowercase) throughout this guide - it's preloaded with all features.

Component Variants

The motion component wraps any HTML or SVG element:

<script setup lang="ts">
import { motion } from 'motion-v'
</script>

<template>
  <!-- HTML elements -->
  <motion.div />
  <motion.span />
  <motion.button />
  <motion.a />
  <motion.img />
  <motion.ul />
  <motion.li />

  <!-- SVG elements -->
  <motion.svg />
  <motion.path />
  <motion.circle />
  <motion.rect />
  <motion.g />
</template>

Animation Props

initial

Starting state before component mounts:

<motion.div :initial="{ opacity: 0, scale: 0.8, x: -100 }">

Set initial: false to disable enter animation and start at animate values.

animate

Target animation state. Changes trigger animation:

<script setup>
const isOpen = ref(false)
</script>

<motion.div :animate="{ height: isOpen ? 'auto' : 0 }">

exit

Animation when component unmounts. Requires AnimatePresence:

<script setup>
import { motion, AnimatePresence } from 'motion-v'
</script>

<template>
  <AnimatePresence>
    <motion.div
      v-if="show"
      :initial="{ opacity: 0 }"
      :animate="{ opacity: 1 }"
      :exit="{ opacity: 0 }"
    />
  </AnimatePresence>
</template>

style

Reactive style object. Use motion values for performant updates:

<motion.div :style="{ x: motionValue, backgroundColor: '#fff' }">

Gesture Props

whileHover

Animation while pointer hovers:

<motion.div
  :whileHover="{ scale: 1.1, backgroundColor: '#f00' }"
  :transition="{ type: 'spring', stiffness: 300 }"
/>

whilePress / whileTap

Animation while element is pressed:

<motion.button :whilePress="{ scale: 0.95 }">

whileFocus

Animation while element has focus:

<motion.input :whileFocus="{ borderColor: '#0066ff', scale: 1.02 }">

whileDrag

Animation while element is being dragged:

<motion.div
  drag
  :whileDrag="{ scale: 1.1, cursor: 'grabbing' }"
  :dragConstraints="{ top: 0, left: 0, right: 300, bottom: 300 }"
/>

Drag Props

<motion.div
  drag              <!-- Enable drag on both axes -->
  drag="x"          <!-- Constrain to x-axis -->
  drag="y"          <!-- Constrain to y-axis -->
  :dragConstraints="{ top: -50, left: -50, right: 50, bottom: 50 }"
  :dragElastic="0.2"        <!-- 0 = rigid, 1 = elastic -->
  :dragMomentum="true"      <!-- Continue with momentum -->
  :dragSnapToOrigin="true"  <!-- Return to start -->
/>

Viewport Props

whileInView

Animation when element enters viewport:

<motion.div
  :initial="{ opacity: 0, y: 50 }"
  :whileInView="{ opacity: 1, y: 0 }"
  :viewport="{ once: true, amount: 0.5 }"
/>

viewport Options

interface ViewportOptions {
  once?: boolean       // Animate only first time (default: false)
  amount?: number | 'some' | 'all'  // Visibility threshold (default: 'some')
  margin?: string      // Rootmargin (e.g., '-100px')
  root?: Element       // Scroll container (default: window)
}

Layout Animation

layout Prop

Automatically animate layout changes:

<motion.div layout>
  <!-- Position/size changes animate smoothly -->
</motion.div>

Layout modes:

<motion.div layout />           <!-- Animate position and size -->
<motion.div layout="position" /> <!-- Position only -->
<motion.div layout="size" />     <!-- Size only -->

layoutId - Shared Element Transitions

Animate between components with matching layoutId:

<script setup>
const selected = ref<string | null>(null)
</script>

<template>
  <div class="grid">
    <motion.div
      v-for="item in items"
      :key="item.id"
      :layoutId="item.id"
      @click="selected = item.id"
    />
  </div>

  <AnimatePresence>
    <motion.div
      v-if="selected"
      :layoutId="selected"
      class="expanded"
    />
  </AnimatePresence>
</template>

LayoutGroup

Sync layout animations across components:

<script setup>
import { motion, LayoutGroup } from 'motion-v'
</script>

<template>
  <LayoutGroup>
    <motion.div layout />
    <motion.div layout />
  </LayoutGroup>
</template>

Transition Configuration

transition Prop

Configure animation behavior:

<motion.div
  :animate="{ x: 100 }"
  :transition="{
    type: 'spring',
    stiffness: 100,
    damping: 10,
    mass: 1,
  }"
/>

Transition Types

Spring (default):

{
  type: 'spring',
  stiffness: 100,  // Higher = snappier (default: 100)
  damping: 10,     // Higher = less bounce (default: 10)
  mass: 1,         // Higher = slower (default: 1)
  velocity: 0,     // Initial velocity
  restDelta: 0.01, // End threshold
}

Tween:

{
  type: 'tween',
  duration: 0.3,
  ease: 'easeOut',  // 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | [0.42, 0, 0.58, 1]
  delay: 0,
  repeat: 0,        // Number of repeats (Infinity for loop)
  repeatType: 'loop',  // 'loop' | 'reverse' | 'mirror'
  repeatDelay: 0,
}

Inertia (for drag):

{
  type: 'inertia',
  velocity: 50,
  power: 0.8,
  timeConstant: 700,
  bounceStiffness: 500,
  bounceDamping: 10,
}

Per-Property Transitions

<motion.div
  :animate="{ x: 100, opacity: 1 }"
  :transition="{
    x: { type: 'spring', stiffness: 100 },
    opacity: { duration: 0.2 },
  }"
/>

AnimatePresence

Animate components as they mount/unmount:

<script setup>
import { motion, AnimatePresence } from 'motion-v'
</script>

<template>
  <AnimatePresence mode="wait">
    <motion.div
      :key="currentPage"
      :initial="{ opacity: 0, x: 100 }"
      :animate="{ opacity: 1, x: 0 }"
      :exit="{ opacity: 0, x: -100 }"
    />
  </AnimatePresence>
</template>

Mode Options

<AnimatePresence mode="sync" />   <!-- Default: animate simultaneously -->
<AnimatePresence mode="wait" />   <!-- Wait for exit before enter -->
<AnimatePresence mode="popLayout" /> <!-- Pop exiting from layout flow -->

Events

<motion.div
  @animationStart="onStart"
  @animationComplete="onComplete"
  @update="onUpdate"              <!-- Called every frame -->
  @hoverStart="onHoverStart"
  @hoverEnd="onHoverEnd"
  @pressStart="onPressStart"
  @pressEnd="onPressEnd"
  @dragStart="onDragStart"
  @drag="onDrag"
  @dragEnd="onDragEnd"
  @viewportEnter="onEnter"
  @viewportLeave="onLeave"
/>

Source: SKILL.md on GitHub

No third-party reports yet.

Signed by skilld at 22e13a9. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 11 hours ago.

Activeupdated 8 months ago

README badge

README badge for onmax/claude-config/motion