athevon/genjutsu5 files

Gsap

GSAP animation engine sub-skill - core, timeline, ScrollTrigger, plugins.

Specification
Skill ID
athevon/genjutsu/gsap
Publisher
athevon
Repository
genjutsu
Installs
0
Files
5
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

athevon/genjutsu/gsapInstalls these files
  • SKILL.md
  • references/core.md
  • references/plugins.md
  • references/scrolltrigger.md
  • references/timeline.md

What this skill tells the agent

Version-sensitive. Every API name, SDK gate and browser-support claim below was verified on 2026-09-08 against primary sources. What against, and when, is in _jutsu/VERSIONS.md. If that date is old, re-verify before acting on a version number.

GSAP — Animation Engine

GSAP 3.15 (released 13 Apr 2026). Since 3.13 the entire library — including every former Club plugin (SplitText, MorphSVG, DrawSVG, ScrollSmoother, InertiaPlugin, MotionPathHelper, CustomEase…) — ships in the public gsap npm package and is free, commercial use included, under the GreenSock Standard "no charge" license. There is no Club paywall. GreenSock also publish official agent skills (MIT, 8 skills: core, timeline, scrolltrigger, plugins, utils, react, performance, frameworks): https://github.com/greensock/gsap-skills — worth installing alongside this sub-skill.

When to use GSAP

CriteriaCSS TransitionsFramer MotionGSAP
Hover / simple toggleYesYesOverkill
Sequenced timelineNoLimitedYes
Scroll-drivenscroll-timelineLimitedScrollTrigger
Complex staggerNoBasicDistribution
Mobile perf (60fps)GoodAverageExcellent
Text splittingNoNoSplitText
SVG morph / drawNoNoMorphSVG
Bundle size concern0kb~30kb~25kb + plugins

Rule: if the animation needs timeline, scroll-link, or distributed stagger, use GSAP. Otherwise CSS first.

Setup

// Always register plugins at the top level
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import { SplitText } from "gsap/SplitText";

gsap.registerPlugin(ScrollTrigger, SplitText);

React: use useGSAP() from the @gsap/react package instead of useEffect + manual cleanup.

import { useGSAP } from "@gsap/react";

useGSAP(() => {
  gsap.to(".box", { x: 200 });
}, { scope: containerRef }); // auto-cleanup, auto-revert

Core Patterns

defaults{} to avoid repetition

const tl = gsap.timeline({
  defaults: { duration: 0.8, ease: "power2.out" },
});
tl.to(".a", { y: -20 })
  .to(".b", { y: -20 }, "<0.1")
  .to(".c", { y: -20 }, "<0.1");

fromTo for full control

gsap.fromTo(".card", { y: 40, opacity: 0 }, { y: 0, opacity: 1, stagger: 0.15 });

Stagger with distribution

gsap.to(".grid-item", {
  scale: 0,
  stagger: {
    each: 0.05,
    from: "center",   // "start" | "end" | "center" | "edges" | "random" | index
    grid: "auto",      // auto-detects the grid
    axis: "x",         // "x" | "y" | null (both)
  },
});

ScrollTrigger Patterns

Basic Pin + Scrub

gsap.to(".panel", {
  x: "-300%",
  ease: "none",
  scrollTrigger: {
    trigger: ".container",
    pin: true,
    scrub: 1,
    end: () => "+=" + document.querySelector(".container").scrollWidth,
  },
});

Batch for mass reveal

ScrollTrigger.batch(".card", {
  onEnter: (elements) => gsap.to(elements, { opacity: 1, y: 0, stagger: 0.1 }),
  start: "top 85%",
});

Horizontal scroll with containerAnimation

const scrollTween = gsap.to(".panels", {
  x: () => -(document.querySelector(".panels").scrollWidth - window.innerWidth),
  ease: "none",
  scrollTrigger: { trigger: ".wrapper", pin: true, scrub: 1 },
});

// Animate elements INSIDE the horizontal scroll
gsap.to(".panel-content", {
  scale: 1.2,
  scrollTrigger: {
    trigger: ".panel-content",
    containerAnimation: scrollTween, // linked to horizontal scroll
    start: "left center",
    end: "right center",
    scrub: true,
  },
});

DO NOT — Critical mistakes

1. Ease on containerAnimation

// BAD — ease breaks the scroll mapping
scrollTrigger: { containerAnimation: scrollTween, scrub: 1, ease: "power2.out" }

// GOOD — always ease: "none" on the parent tween
const scrollTween = gsap.to(".panels", { x: ..., ease: "none", scrollTrigger: { scrub: 1 } });

2. ScrollTrigger on a child tween in a timeline

// BAD — ScrollTrigger ignores child tweens of a timeline that has its own ScrollTrigger
const tl = gsap.timeline({ scrollTrigger: { trigger: ".section" } });
tl.to(".box", { x: 100, scrollTrigger: { trigger: ".box" } }); // IGNORE

// GOOD — one ScrollTrigger per timeline OR standalone tweens
gsap.to(".box", { x: 100, scrollTrigger: { trigger: ".box" } }); // tween standalone

3. setState in onUpdate

// BAD — setState 60x/s = re-render hell
scrollTrigger: { onUpdate: (self) => setProgress(self.progress) }

// GOOD — mutate a ref or DOM element directly
const progressRef = useRef(0);
scrollTrigger: { onUpdate: (self) => { progressRef.current = self.progress; } }
// Or better: gsap.quickSetter to mutate the DOM without React

4. immediateRender on from() in a timeline

// BAD — from() has immediateRender: true by default, breaks sequencing
tl.to(".box", { x: 100 });
tl.from(".box", { y: 50 }); // visually jumps to the start

// GOOD — disable immediateRender when from() follows another tween
tl.to(".box", { x: 100 });
tl.from(".box", { y: 50, immediateRender: false });

5. Animating non-transform properties

// BAD — width/height/top/left trigger layout reflow
gsap.to(".box", { width: 200, height: 200 });

// GOOD — use transforms (GPU-accelerated, composited)
gsap.to(".box", { scaleX: 1.5, scaleY: 1.5 });
// If actual size needed: use Flip plugin for layout transition

Refs

  • references/core.md — Complete gsap.to/from/fromTo/set API, options
  • references/timeline.md — Timeline, position parameter, nesting
  • references/scrolltrigger.md — Full ScrollTrigger reference
  • references/plugins.md — SplitText, Flip, MorphSVG, DrawSVG, MotionPath, Observer

Use this skill in a project

Open any RiverX project, search the Skills panel for athevon/genjutsu/gsap, and install it in one click.

Use this skill