Install
$ agentstack add skill-gabelul-stitch-kit-stitch-animate ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
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:
- Interactive elements that need Micro tier (buttons, links, inputs, toggles, cards with
onClick) - Revealed elements that benefit from Meso tier (page sections, cards grids, sidebars, modals, drawers, toasts)
- 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 (
{children}
)
}
Staggered card grid
'use client'
import { motion, useReducedMotion } from 'framer-motion'
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: { staggerChildren: 0.08 }
}
}
const item = {
hidden: { opacity: 0, y: 16 },
show: { opacity: 1, y: 0, transition: { ease: [0, 0, 0.2, 1], duration: 0.35 } }
}
export function AnimatedGrid({ cards }: { cards: CardProps[] }) {
const shouldReduce = useReducedMotion()
if (shouldReduce) {
return {cards.map(c => )}
}
return (
{cards.map(c => (
))}
)
}
Page transition wrapper (App Router)
// app/template.tsx — wraps every page with a transition
'use client'
import { motion } from 'framer-motion'
export default function Template({ children }: { children: React.ReactNode }) {
return (
{children}
)
}
Approach C: Svelte transitions (Svelte / SvelteKit)
Svelte's built-in transitions are the cleanest option for Svelte projects — zero dependencies.
Intersection Observer for scroll reveals
Svelte doesn't have a built-in scroll reveal, but the use: directive makes this clean:
import { fade, fly } from 'svelte/transition'
import { cubicOut } from 'svelte/easing'
/**
* Svelte action that triggers a fade-up animation when the element
* enters the viewport. Respects prefers-reduced-motion.
*/
function revealOnScroll(node: HTMLElement) {
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
if (prefersReduced) return {}
node.style.opacity = '0'
node.style.transform = 'translateY(16px)'
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
node.style.transition = `opacity 400ms cubic-bezier(0,0,0.2,1), transform 400ms cubic-bezier(0,0,0.2,1)`
node.style.opacity = '1'
node.style.transform = 'translateY(0)'
observer.unobserve(node)
}
},
{ threshold: 0.1, rootMargin: '-50px' }
)
observer.observe(node)
return {
destroy() { observer.disconnect() }
}
}
This section fades in on scroll
Animated list entries
import { fly } from 'svelte/transition'
import { quintOut } from 'svelte/easing'
let items = $state([...])
{#each items as item, i (item.id)}
{/each}
Modal/drawer with enter/exit
import { fade, fly } from 'svelte/transition'
let { isOpen = false } = $props()
{#if isOpen}
{@render children()}
{/if}
Step 3: Apply animations to existing components
When modifying existing files:
- Read each component file first — understand the current structure
- Add CSS classes for Micro tier only (never change the component's logic for Micro)
- Wrap with motion components for Meso/Macro (React) or add transition directives (Svelte)
- Add the reduced-motion override to the main CSS file if not already present
- Test both states — with and without animation (use browser DevTools to simulate reduced motion)
What NOT to animate
- Navigation links — stick to color/underline transitions only
- Scrolling behavior — only
scroll-behavior: smoothwhere appropriate, and even that needs the reduced-motion override - Data tables — distract from reading; use subtle row hover only
- Every element on a page — choose 2-3 anchor animations per screen
Troubleshooting
| Issue | Fix | |-------|-----| | Animation not playing | Check the element is in the DOM before the animation fires | | Framer Motion hydration error | Ensure component has 'use client' directive | | Svelte transition plays twice | Check for double-render in dev mode (StrictMode equivalent) | | Animation jank/lag | Add will-change: transform, opacity sparingly to animated elements | | Reduced motion not stopping animation | Ensure @media (prefers-reduced-motion) is loaded AFTER animation CSS |
References
resources/animation-patterns.md— Catalog of copy-paste ready patterns for common UI components
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: gabelul
- Source: gabelul/stitch-kit
- License: Apache-2.0
- Homepage: https://booplex.com/projects/stitch-kit-design-intelligence-for-ai-agents
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.