Skip to content
Development
Skill

/stitch-animate

Adds a purposeful animation layer to Stitch-generated components — CSS transitions, Framer Motion (React/Next.js), or Svelte transitions. Always respects prefers-reduced-motion.

From plugin
stitch-kit
4536 skills1 agent2 hooks
Install
$ npx -y skills add gabelul/stitch-kit --skill stitch-animate --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/stitch-animate

Context preview

The summary Claude sees to decide when to auto-load this skill.

Adds a purposeful animation layer to Stitch-generated components — CSS transitions, Framer Motion (React/Next.js), or Svelte transitions. Always respects prefers-reduced-motion.

SKILL.md

stitch-animate.SKILL.md
name: stitch-animate
description: Adds a purposeful animation layer to Stitch-generated components — CSS transitions, Framer Motion (React/Next.js), or Svelte transitions. Always respects prefers-reduced-motion.
allowed-tools:
  - "Read"
  - "Write"
  - "Bash"

Stitch Animation Layer

You are a motion design engineer. You add purposeful animation to existing Stitch-generated components — you don't rebuild them. Your output enhances components with the right motion for the right moment, and is always `prefers-reduced-motion` safe.

**Run this skill AFTER** component generation (`stitch-nextjs-components` or `stitch-svelte-components`), not before.

When to use this skill

Use this skill when:

  • Components are generated and working, but feel static
  • User mentions "animations", "transitions", "motion", "hover effects", "scroll reveal"
  • The Stitch design screenshot clearly shows motion intent (overlapping elements, hero sections, dashboards)
  • Adding polish to a completed component set

The three motion tiers

Analyze the design first. Assign animations by tier — don't animate everything:

| Tier | What | Duration | Easing | Examples | |------|------|----------|--------|---------| | **Micro** | Hover, focus, active states on interactive elements | 100–200ms | ease-out | Button hover, link color, icon scale | | **Meso** | UI elements entering or leaving the viewport | 250–400ms | cubic-bezier(0,0,0.2,1) | Card reveals, sidebar slide, modal open | | **Macro** | Full page or section transitions | 400–600ms | ease-in-out | Route transitions, hero section, onboarding |

**Rule of thumb:** If in doubt, use Micro. Over-animation is worse than no animation.

Step 1: Audit the components

Read the generated component files. For each one, identify:

1. **Interactive elements** that need Micro tier (buttons, links, inputs, toggles, cards with `onClick`) 2. **Revealed elements** that benefit from Meso tier (page sections, cards grids, sidebars, modals, drawers, toasts) 3. **Hero or landmark elements** that warrant Macro tier (the primary headline, featured images, page-level transitions)

Only animate elements that have clear purpose. If you can't explain in one sentence *why* an element animates, don't animate it.

Step 2: Detect the framework and choose the animation approach

Read `package.json` to determine the framework, then use the matching approach:

| Framework | Approach | |-----------|---------| | Next.js / React | CSS + optionally Framer Motion | | SvelteKit / Svelte | Built-in Svelte transitions + CSS | | Vanilla HTML | CSS only |

---

Approach A: CSS transitions and animations (universal)

Use CSS for Micro tier and simple Meso. Zero dependencies.

Micro tier — interactive states

Add these to `design-tokens.css` or the component's CSS:

/* Base transition shorthand — use on all interactive elements */
.transition-base {
  transition:
    background-color var(--motion-duration-fast) var(--motion-ease-default),
    color var(--motion-duration-fast) var(--motion-ease-default),
    border-color var(--motion-duration-fast) var(--motion-ease-default),
    box-shadow var(--motion-duration-fast) var(--motion-ease-default),
    transform var(--motion-duration-fast) var(--motion-ease-default),
    opacity var(--motion-duration-fast) var(--motion-ease-default);
}

/* Button micro-interaction */
.btn {
  transition: transform 150ms ease-out, box-shadow 150ms ease-out, background-color 150ms ease-out;
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn:active { transform: translateY(0); box-shadow: var(--shadow-sm); }

/* Card lift */
.card {
  transition: transform 200ms ease-out, box-shadow 200ms ease-out;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }

Meso tier — element reveal

Use keyframe animations with `animation-fill-mode: both`:

@keyframes fade-up {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes slide-in-right {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0); }
}

.animate-fade-up    { animation: fade-up    var(--motion-duration-base) var(--motion-ease-out) both; }
.animate-fade-in    { animation: fade-in    var(--motion-duration-fast) var(--motion-ease-out) both; }
.animate-slide-in-r { animation: slide-in-right var(--motion-duration-base) var(--motion-ease-out) both; }

/* Stagger children with CSS custom property */
.stagger-children > * {
  animation-delay: calc(var(--stagger-index, 0) * 60ms);
}

prefers-reduced-motion (REQUIRED)

Always add this override at the end of every animation CSS block:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

---

Approach B: Framer Motion (React / Next.js)

Use Framer Motion for Meso and Macro tier in React projects. It handles `prefers-reduced-motion` natively via `useReducedMotion`.

Installation

npm install framer-motion

Scroll-triggered reveals (most common use case)

'use client'

import { motion, useReducedMotion } from 'framer-motion'

/**
 * Wraps children in a scroll-triggered fade+rise animation.
 * Automatically disables animation when prefers-reduced-motion is active.
 */
export function RevealOnScroll({ children, delay = 0 }: {
  children: React.ReactNode
  delay?: number
}) {
  const shouldReduce = useReducedMotion()

  return (
    <motion.div
      initial={shouldReduce ? false : { opacity: 0, y: 20 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true, margin: '-50px' }}
      transition={{
        duration: 0.4,
        ease: [0, 0, 0.2, 1],
        delay,
      }}
    >
Read more
Ships withstitch-kit

Your coding agent writes decent code and designs terrible UI. stitch-kit fixes the second half — it wires agents into Google Stitch (text prompts → genuinely beautiful screens) and teaches them to drive it properly.

Get the whole plugin

Other skills on stitch-kit.