animejs-mastery

Anime.js Animation Upgrade Agent

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "animejs-mastery" with this command: npx skills add frogody/app.isyncso/frogody-app-isyncso-animejs-mastery

Anime.js Animation Upgrade Agent

Autonomous agent that analyzes codebases and systematically implements polished, performant animations using anime.js.

Agent Workflow

Execute these phases sequentially. Work autonomously—don't ask for permission between steps.

Phase 1: Codebase Analysis

1. Identify framework and structure

find . -name "package.json" -o -name ".tsx" -o -name ".jsx" -o -name ".vue" -o -name ".svelte" | head -20

2. Check if anime.js is installed

grep -r "animejs|anime.js" package.json 2>/dev/null || echo "NOT_INSTALLED"

3. Map component structure

find . -type f ( -name ".tsx" -o -name ".jsx" -o -name ".vue" ) -path "/components/*" | head -50

Install anime.js if missing:

npm install animejs

For TypeScript projects:

npm install --save-dev @types/animejs

Phase 2: Opportunity Identification

Scan the codebase for these high-impact animation opportunities:

Priority Pattern to Find Animation Type

P0 Page/route transitions Fade + slide sequences

P0 Loading states, spinners Smooth pulsing/rotation

P1 Lists rendering data Staggered entrance

P1 Modals/dialogs/drawers Scale + fade entrance

P1 Form submissions Success/error feedback

P2 Buttons, CTAs Hover/press micro-interactions

P2 Cards, tiles Hover lift effects

P2 Data visualizations Number counting, chart reveals

P3 Icons, badges Attention pulses

P3 Tooltips, popovers Soft entrance

Search patterns:

Find loading states

grep -rn "loading|isLoading|skeleton|Spinner" --include=".tsx" --include=".jsx"

Find modals/dialogs

grep -rn "Modal|Dialog|Drawer|Sheet" --include=".tsx" --include=".jsx"

Find lists with map

grep -rn ".map(" --include=".tsx" --include=".jsx" | grep -i "item|card|row"

Find buttons

grep -rn "<button|<Button|onClick" --include=".tsx" --include=".jsx"

Find route transitions

grep -rn "Route|router|navigate|Link" --include=".tsx" --include=".jsx"

Phase 3: Create Animation Utilities

Create a shared animation utilities file first:

// src/lib/animations.ts (or utils/animations.ts) import anime from 'animejs';

// Respect user preferences export const prefersReducedMotion = () => typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

// Safe animate wrapper export const safeAnimate = ( targets: anime.AnimeParams['targets'], params: Omit<anime.AnimeParams, 'targets'> ) => { if (prefersReducedMotion()) { return anime({ targets, ...params, duration: 0 }); } return anime({ targets, ...params }); };

// Staggered list entrance export const staggerIn = (selector: string, delay = 50) => safeAnimate(selector, { translateY: [20, 0], opacity: [0, 1], delay: anime.stagger(delay), duration: 400, easing: 'easeOutQuad', });

// Modal entrance export const modalIn = (selector: string) => safeAnimate(selector, { scale: [0.95, 1], opacity: [0, 1], duration: 200, easing: 'easeOutQuad', });

// Button press feedback export const buttonPress = (element: HTMLElement) => safeAnimate(element, { scale: [1, 0.97, 1], duration: 150, easing: 'easeInOutQuad', });

// Success animation export const successPop = (selector: string) => safeAnimate(selector, { scale: [0, 1.1, 1], opacity: [0, 1], duration: 400, easing: 'easeOutBack', });

// Error shake export const errorShake = (selector: string) => safeAnimate(selector, { translateX: [0, -8, 8, -8, 8, -4, 4, 0], duration: 400, easing: 'easeInOutQuad', });

// Fade out (for exits) export const fadeOut = (selector: string) => safeAnimate(selector, { opacity: [1, 0], translateY: [0, -10], duration: 200, easing: 'easeInQuad', });

// Number counter export const countUp = ( element: HTMLElement, endValue: number, duration = 1000 ) => { const obj = { value: 0 }; return anime({ targets: obj, value: endValue, round: 1, duration, easing: 'easeOutExpo', update: () => { element.textContent = obj.value.toLocaleString(); }, }); };

// Skeleton pulse export const skeletonPulse = (selector: string) => safeAnimate(selector, { opacity: [0.5, 1, 0.5], duration: 1500, loop: true, easing: 'easeInOutSine', });

Phase 4: React Hook Pattern

Create reusable hooks for React projects:

// src/hooks/useAnimation.ts import { useEffect, useRef, useCallback } from 'react'; import anime from 'animejs'; import { prefersReducedMotion } from '@/lib/animations';

export function useStaggeredEntrance<T extends HTMLElement>( deps: unknown[] = [] ) { const containerRef = useRef<T>(null);

useEffect(() => { if (!containerRef.current || prefersReducedMotion()) return;

const children = containerRef.current.children;
anime({
  targets: children,
  translateY: [20, 0],
  opacity: [0, 1],
  delay: anime.stagger(50),
  duration: 400,
  easing: 'easeOutQuad',
});

}, deps);

return containerRef; }

export function useButtonFeedback() { const handlePress = useCallback((e: React.MouseEvent<HTMLElement>) => { if (prefersReducedMotion()) return;

anime({
  targets: e.currentTarget,
  scale: [1, 0.97, 1],
  duration: 150,
  easing: 'easeInOutQuad',
});

}, []);

return { onMouseDown: handlePress }; }

export function useHoverLift<T extends HTMLElement>() { const ref = useRef<T>(null);

useEffect(() => { const el = ref.current; if (!el || prefersReducedMotion()) return;

const enter = () => {
  anime.remove(el);
  anime({
    targets: el,
    translateY: -4,
    boxShadow: '0 8px 30px rgba(0,0,0,0.12)',
    duration: 200,
    easing: 'easeOutQuad',
  });
};

const leave = () => {
  anime.remove(el);
  anime({
    targets: el,
    translateY: 0,
    boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
    duration: 200,
    easing: 'easeOutQuad',
  });
};

el.addEventListener('mouseenter', enter);
el.addEventListener('mouseleave', leave);
return () => {
  el.removeEventListener('mouseenter', enter);
  el.removeEventListener('mouseleave', leave);
};

}, []);

return ref; }

export function useCountUp(endValue: number, duration = 1000) { const ref = useRef<HTMLElement>(null);

useEffect(() => { if (!ref.current) return;

const obj = { value: 0 };
anime({
  targets: obj,
  value: endValue,
  round: 1,
  duration: prefersReducedMotion() ? 0 : duration,
  easing: 'easeOutExpo',
  update: () => {
    if (ref.current) {
      ref.current.textContent = obj.value.toLocaleString();
    }
  },
});

}, [endValue, duration]);

return ref; }

Phase 5: Implementation Checklist

Work through components systematically. For each component:

  • Identify the animation opportunity (entrance, interaction, feedback)

  • Add necessary imports

  • Implement using utilities/hooks

  • Test reduced-motion behavior

  • Verify 60fps performance

Implementation order:

  • Animation utilities file

  • React hooks (if React project)

  • P0: Page transitions, loading states

  • P1: Lists, modals, form feedback

  • P2: Buttons, cards

  • P3: Icons, tooltips

Phase 6: Common Implementation Patterns

List component with staggered entrance:

function ItemList({ items }) { const listRef = useStaggeredEntrance<HTMLUListElement>([items]);

return ( <ul ref={listRef}> {items.map(item => ( <li key={item.id} style={{ opacity: 0 }}> {item.name} </li> ))} </ul> ); }

Button with press feedback:

function AnimatedButton({ children, onClick, ...props }) { const feedbackProps = useButtonFeedback();

return ( <button {...props} {...feedbackProps} onClick={onClick}> {children} </button> ); }

Card with hover lift:

function Card({ children }) { const cardRef = useHoverLift<HTMLDivElement>();

return ( <div ref={cardRef} className="card"> {children} </div> ); }

Modal with entrance animation:

function Modal({ isOpen, children }) { const modalRef = useRef<HTMLDivElement>(null);

useEffect(() => { if (isOpen && modalRef.current) { modalIn(modalRef.current); } }, [isOpen]);

if (!isOpen) return null;

return ( <div ref={modalRef} className="modal" style={{ opacity: 0 }}> {children} </div> ); }

Performance Rules

ALWAYS animate (GPU-accelerated):

  • translateX , translateY , translateZ

  • scale , rotate

  • opacity

NEVER animate (triggers layout):

  • width , height

  • padding , margin

  • top , left , right , bottom

Timing guidelines:

Type Duration Easing

Micro-interaction 100-200ms easeOutQuad

Button feedback 150ms easeInOutQuad

Modal entrance 200-250ms easeOutQuad

List stagger 50-100ms between easeOutQuad

Page transition 300ms easeOutQuint

Output Format

After implementation, provide a summary:

Animation Upgrade Summary

Files Created

  • src/lib/animations.ts - Core utilities
  • src/hooks/useAnimation.ts - React hooks

Components Updated

ComponentAnimation AddedPriority
ItemListStaggered entranceP1
ModalScale + fade inP1
ButtonPress feedbackP2

Performance Notes

  • All animations use transform/opacity only
  • Reduced motion respected globally
  • Average animation duration: 200ms

Reference Files

For detailed API documentation: references/api-reference.md

For additional patterns: references/patterns.md

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

clinic-visit-prep

帮助患者整理就诊前问题、既往记录、检查清单与时间线,不提供诊断。;use for healthcare, intake, prep workflows;do not use for 给诊断结论, 替代医生意见.

Archived SourceRecently Updated
Automation

changelog-curator

从变更记录、提交摘要或发布说明中整理对外 changelog,并区分用户价值与内部改动。;use for changelog, release-notes, docs workflows;do not use for 捏造未发布功能, 替代正式合规审批.

Archived SourceRecently Updated
Automation

klaviyo

Klaviyo API integration with managed OAuth. Access profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks. Use this skill when users want to manage email marketing, customer data, or integrate with Klaviyo workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

Archived SourceRecently Updated