mcpField
M
motion

motion

github.com/mindrallyDesign & UI288827 installsUpdated 3w ago
Repository

About motion

A Motion animation skill for JavaScript and TypeScript web developers. It covers animation composition, scroll and viewport triggers, playback controls, performance, and reduced-motion preferences.

Key features

  1. 01Element and keyframe animations
  2. 02Timeline sequencing and controls
  3. 03Scroll-linked and in-view effects
  4. 04Stagger and spring animations
  5. 05Playback events and cancellation
  6. 06Performance and reduced-motion guidance

Use cases

  1. 01Animate page elements and sequences
  2. 02Build scroll-responsive effects
  3. 03Trigger animations when elements enter view
  4. 04Adapt animations for reduced-motion preferences

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/mindrally/skills --skill motion

After installing, type/motionin Claude Code to confirm it loaded.

Details

From the project README

Motion Animation Guidelines

You are an expert in Motion (motion.dev), JavaScript, TypeScript, and web animation performance. Follow these guidelines when creating animations.

Core Principles

About Motion
  • Motion is the JavaScript animation library from the creator of Framer Motion
  • Use motion for vanilla JavaScript/TypeScript projects
  • Use motion/react for React projects (see framer-motion skill)
  • Designed for high performance with minimal bundle size
Installation
npm install motion
Basic Import
import { animate, scroll, inView, timeline } from "motion";

Basic Animations

Simple Animation
import { animate } from "motion";

// Animate a single element
animate(".element", { x: 100, opacity: 1 }, { duration: 0.5 });

// Animate with options
animate(
  ".element",
  { transform: "translateX(100px)" },
  {
    duration: 0.8,
    easing: "ease-out"
  }
);
Keyframes
animate(
  ".element",
  {
    x: [0, 100, 50],      // Keyframe values
    opacity: [0, 1, 0.5]
  },
  { duration: 1 }
);

Performance Optimization

Animate Transform Properties
// Best performance - GPU accelerated
animate(".element", {
  x: 100,           // translateX
  y: 50,            // translateY
  scale: 1.2,       // scale
  rotate: 45,       // rotate
  opacity: 0.5      // opacity
});

// Avoid when possible - triggers layout
animate(".element", {
  width: 200,       // Causes layout recalculation
  height: 150,      // Causes layout recalculation
  top: 50,          // Causes layout recalculation
  left: 100         // Causes layout recalculation
});
Use will-change
// Add will-change for transform animations
const element = document.querySelector(".element");
element.style.willChange = "transform";

animate(element, { x: 100 }, {
  onComplete: () => {
    element.style.willChange = "auto"; // Remove after animation
  }
});
Hardware Acceleration

Motion automatically uses hardware-accelerated properties when possible. For best performance:

  1. Prefer x, y over left, top
  2. Prefer scale over width, height
  3. Use opacity for fade effects
  4. Use rotate over transform: rotate()

Timeline Animations

Create Timelines
import { timeline } from "motion";

const sequence = [
  [".header", { y: ["-100%", 0], opacity: [0, 1] }],
  [".content", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }],
  [".footer", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }]
];

const controls = timeline(sequence, {
  duration: 0.8,
  defaultOptions: { easing: "ease-out" }
});
Timeline Controls
const controls = timeline(sequence);

controls.play();
controls.pause();
controls.reverse();
controls.stop();
controls.finish();

// Seek to specific time
controls.currentTime = 0.5;

Scroll Animations

Basic Scroll Animation
import { scroll, animate } from "motion";

scroll(
  animate(".progress-bar", { scaleX: [0, 1] }),
  { target: document.querySelector("article") }
);
Scroll-Linked Animation
scroll(({ y }) => {
  // y.progress is 0 to 1
  animate(".element", {
    opacity: y.progress,
    y: y.progress * 100
  }, { duration: 0 });
});
Scroll with Container
scroll(
  animate(".parallax", { y: [0, -100] }),
  {
    target: document.querySelector(".section"),
    offset: ["start end", "end start"]
  }
);

In-View Animations

Trigger on Visibility
import { inView, animate } from "motion";

inView(".card", (info) => {
  animate(info.target, { opacity: 1, y: 0 }, { duration: 0.5 });

  // Return cleanup function
  return () => {
    animate(info.target, { opacity: 0, y: 20 }, { duration: 0.2 });
  };
});
With Options
inView(
  ".element",
  (info) => {
    animate(info.target, { scale: [0.8, 1], opacity: [0, 1] });
  },
  {
    margin: "-100px",  // Trigger 100px before entering viewport
    amount: 0.5        // Trigger when 50% visible
  }
);

Stagger Animations

Stagger Multiple Elements
import { stagger, animate } from "motion";

animate(
  ".list-item",
  { opacity: [0, 1], y: [20, 0] },
  { delay: stagger(0.1) }
);
Stagger from Center
animate(
  ".grid-item",
  { scale: [0, 1] },
  { delay: stagger(0.05, { from: "center" }) }
);
Stagger with Easing
animate(
  ".item",
  { x: ["-100%", 0] },
  {
    delay: stagger(0.1, {
      easing: "ease-out",
      start: 0.2
    })
  }
);

Spring Animations

Use Springs for Natural Motion
animate(
  ".element",
  { scale: 1.2 },
  {
    easing: "spring",
    // or with custom spring settings
    easing: [0.34, 1.56, 0.64, 1] // Custom bezier curve
  }
);
Spring Options
animate(".element", { x: 100 }, {
  type: "spring",
  stiffness: 300,
  damping: 30
});

Easing Functions

Built-in Easings
// Common easing values
animate(".element", { x: 100 }, { easing: "ease" });
animate(".element", { x: 100 }, { easing: "ease-in" });
animate(".element", { x: 100 }, { easing: "ease-out" });
animate(".element", { x: 100 }, { easing: "ease-in-out" });
animate(".element", { x: 100 }, { easing: "linear" });

// Cubic bezier
animate(".element", { x: 100 }, {
  easing: [0.25, 0.1, 0.25, 1]
});

Animation Controls

Control Playback
const controls = animate(".element", { x: 100 }, { duration: 1 });

// Control methods
controls.play();
controls.pause();
controls.stop();
controls.finish();
controls.reverse();

// Get/set time
controls.currentTime = 0.5;
console.log(controls.duration);

// Cancel animation
controls.cancel();
Animation Events
const controls = animate(
  ".element",
  { x: 100 },
  {
    duration: 1,
    onComplete: () => console.log("Done!")
  }
);

// Promise-based
controls.finished.then(() => {
  console.log("Animation finished");
});

Accessibility

Respect Reduced Motion
const prefersReducedMotion = window.matchMedia(
  "(prefers-reduced-motion: reduce)"
).matches;

animate(
  ".element",
  { x: 100, opacity: 1 },
  {
    duration: prefersReducedMotion ? 0 : 0.5,
    easing: prefersReducedMotion ? "linear" : "ease-out"
  }
);
Create Accessible Wrapper
function safeAnimate(element, keyframes, options = {}) {
  const reducedMotion = window.matchMedia(
    "(prefers-reduced-motion: reduce)"
  ).matches;

  return animate(element, keyframes, {
    ...options,
    duration: reducedMotion ? 0 : (options.duration ?? 0.3)
  });
}

Integration with Frameworks

Vanilla JavaScript
document.addEventListener("DOMContentLoaded", () => {
  animate(".hero", { opacity: [0, 1], y: [30, 0] });
});
With Event Listeners
const button = document.querySelector(".button");

button.addEventListener("mouseenter", () => {
  animate(button, { scale: 1.05 }, { duration: 0.2 });
});

button.addEventListener("mouseleave", () => {
  animate(button, { scale: 1 }, { duration: 0.2 });
});

Cleanup

Cancel Animations
const controls = animate(".element", { x: 100 });

// Later, cancel it
controls.cancel();
Cleanup Pattern
class AnimatedComponent {
  constructor(element) {
    this.element = element;
    this.animations = [];
  }

  animate(keyframes, options) {
    const controls = animate(this.element, keyframes, options);
    this.animations.push(controls);
    return controls;
  }

  destroy() {
    this.animations.forEach(anim => anim.cancel());
    this.animations = [];
  }
}

Best Practices Summary

  1. Use transform properties (x, y, scale, rotate) for best performance
  2. Add will-change before complex animations, remove after
  3. Use timeline for sequenced animations
  4. Use scroll() for scroll-linked effects
  5. Use inView() for viewport-triggered animations
  6. Use stagger() for animating multiple elements
  7. Prefer springs for interactive/gesture animations
  8. Always respect reduced motion preferences
  9. Cancel animations when no longer needed
  10. Test performance on actual devices

Comments

Markdown supported