mirror of
https://github.com/greensock/gsap-skills
synced 2026-09-22 23:34:24 +08:00
Added Github Copilot support
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# GSAP — Repository-wide instructions for GitHub Copilot
|
||||
|
||||
When writing or suggesting GSAP (GreenSock Animation Platform) code in this repository:
|
||||
|
||||
- **Imports:** Use `import { gsap } from "gsap"` (or named plugin imports, e.g. `import { ScrollTrigger } from "gsap/ScrollTrigger"`). Register plugins once with `gsap.registerPlugin(ScrollTrigger)` before use.
|
||||
- **Sequencing:** Prefer `gsap.timeline()` for multi-step animations instead of chained `delay` values. Use the position parameter (e.g. `"+=0.5"`, `"<"`, `"label"`) to place tweens on the timeline.
|
||||
- **Transforms:** Prefer GSAP transform properties (`x`, `y`, `scale`, `rotation`, `xPercent`, `yPercent`) over animating raw CSS `transform` or layout properties (`top`, `left`, `width`, `height`) for movement and scale — better performance and consistent order of operations.
|
||||
- **Opacity:** Prefer `autoAlpha` over `opacity` for fade in/out so elements get `visibility: hidden` at 0 and do not block clicks.
|
||||
- **from() / fromTo():** `gsap.from()` animates from the given values to the element’s current state. When **multiple from() or fromTo()** tweens target the same property of the same element, set **immediateRender: false** on the later one(s) so the first tween’s end state is not overwritten before it runs.
|
||||
- **Scroll-based animation:** When scroll-driven or scroll-linked animation is requested, use ScrollTrigger (register the plugin, then use `scrollTrigger: { trigger, start, end, scrub }` or attach to a timeline). Do **not** put a ScrollTrigger on a tween that is a child of a timeline — put it on the timeline or a top-level tween.
|
||||
- **ScrollTrigger:** Use **scrub** for scroll-linked progress or **toggleActions** for discrete play/reverse, not both. Call **ScrollTrigger.refresh()** after DOM/layout changes that affect trigger positions. Create ScrollTriggers in top-to-bottom page order or set **refreshPriority** so they refresh in that order.
|
||||
- **React:** In React projects, prefer `useGSAP()` (from `@gsap/react`) or `gsap.context()` with cleanup so animations and ScrollTriggers are reverted when the component unmounts.
|
||||
- **Cleanup:** When elements are removed or routes change (e.g. SPAs), kill associated ScrollTrigger instances or revert SplitText/Draggable so nothing runs on stale elements. Use **clearProps** when a tween should not leave inline styles after it completes (e.g. so CSS classes can take over).
|
||||
|
||||
**More detail:** The `skills/` directory in this repo contains full SKILL.md guidance (core, timeline, ScrollTrigger, plugins, React, performance). For agents that support the Agent Skills format (Cursor, Claude Code, etc.), install this repo as a skill for the complete reference.
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
applyTo: ["**/*.tsx", "**/*.jsx", "**/components/**"]
|
||||
---
|
||||
|
||||
# GSAP in React — path-specific instructions
|
||||
|
||||
When writing or suggesting GSAP code in React/JSX/TSX files:
|
||||
|
||||
- Prefer **useGSAP()** from `@gsap/react` over raw `useEffect` for GSAP setup. Register the hook once: `gsap.registerPlugin(useGSAP)` (and any other plugins used).
|
||||
- Pass a **scope** (ref to container) so selectors are scoped: `useGSAP(() => { ... }, { scope: containerRef })`. This avoids animating elements outside the component.
|
||||
- When targeting by ref, pass the **DOM element** (e.g. `ref.current`), not the ref object. Wrong: `gsap.to(myRef, ...)`. Right: `gsap.to(myRef.current, ...)`. With useGSAP, the scope ref limits selectors to that subtree.
|
||||
- Rely on useGSAP’s automatic **cleanup** on unmount (reverts animations and kills ScrollTriggers). Do not leave ScrollTriggers or timelines running after unmount.
|
||||
- Use **contextSafe** (returned from useGSAP) to wrap callbacks like `onComplete` so they no-op after unmount and avoid React state-update warnings.
|
||||
- By default useGSAP runs once (empty dependency array). To re-run when deps change, pass `{ dependencies: [dep1, dep2] }` or `{ revertOnUpdate: true }` as the second argument. Put animation logic in the callback, not in a separate effect.
|
||||
- If not using useGSAP, use **gsap.context()** in useEffect and return a cleanup that calls `ctx.revert()`.
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
applyTo: ["**/*scroll*", "**/*ScrollTrigger*", "**/scroll*"]
|
||||
---
|
||||
|
||||
# ScrollTrigger — path-specific instructions
|
||||
|
||||
When writing or suggesting scroll-linked GSAP code (ScrollTrigger):
|
||||
|
||||
- Register the plugin once: `gsap.registerPlugin(ScrollTrigger)`.
|
||||
- Use **scrub: true** (or a number) for scroll-driven progress; use **toggleActions** for discrete play/reverse. Do not use both on the same trigger.
|
||||
- Put ScrollTrigger on the **timeline** or a **top-level tween**, not on a tween that is a child of a timeline (wrong: `tl.to(..., { scrollTrigger: {... } })`; right: `gsap.timeline({ scrollTrigger: {... } }).to(...)`).
|
||||
- When **pinning**, do not animate the pinned element itself; animate its children. Use **pinSpacing: true** (default) so layout does not collapse.
|
||||
- Prefer **transform** properties (`x`, `y`, `scale`, `rotation`) for the animated element; avoid animating layout properties when possible.
|
||||
- For “fake” horizontal scroll (pin a section, content moves horizontally while scrolling vertically), use **containerAnimation** and set **ease: "none"** on the horizontal tween so scroll and position stay in sync.
|
||||
- **start** / **end** format: `"triggerPosition viewportPosition"` (e.g. `"top center"`, `"bottom top"`). Use `endTrigger` if the end is based on a different element.
|
||||
- Call **ScrollTrigger.refresh()** after DOM or layout changes that affect trigger positions (e.g. new content, fonts loaded). Viewport resize is handled automatically.
|
||||
- Create ScrollTriggers in **top-to-bottom** page order, or set **refreshPriority** so they refresh in that order when creation order differs.
|
||||
- When removing elements or changing routes (SPAs), **kill** ScrollTrigger instances: `ScrollTrigger.getAll().forEach(t => t.kill())` or kill by id.
|
||||
Reference in New Issue
Block a user