akili-specs 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/akili-archive.md +9 -0
- package/.claude/commands/akili-audit.md +9 -0
- package/.claude/commands/akili-constitution.md +41 -3
- package/.claude/commands/akili-execute.md +10 -1
- package/.claude/commands/akili-propose.md +9 -0
- package/.claude/commands/akili-quick.md +9 -0
- package/.claude/commands/akili-resume.md +9 -0
- package/.claude/commands/akili-seo.md +9 -0
- package/.claude/commands/akili-specify.md +14 -2
- package/.claude/commands/akili-test.md +9 -0
- package/.claude/commands/akili-validate.md +9 -0
- package/.claude/skills/angular-developer/SKILL.md +4 -0
- package/.claude/skills/api-design-principles/SKILL.md +8 -0
- package/.claude/skills/aws-serverless/SKILL.md +8 -1
- package/.claude/skills/brainstorming/SKILL.md +25 -1
- package/.claude/skills/cognitive-doc-design/SKILL.md +14 -0
- package/.claude/skills/error-handling-patterns/SKILL.md +8 -0
- package/.claude/skills/frontend-design/SKILL.md +8 -1
- package/.claude/skills/gsap-animation/SKILL.md +182 -0
- package/.claude/skills/gsap-animation/references/frameworks.md +137 -0
- package/.claude/skills/{gsap-performance/SKILL.md → gsap-animation/references/performance.md} +10 -20
- package/.claude/skills/gsap-animation/references/plugins.md +390 -0
- package/.claude/skills/gsap-animation/references/react.md +122 -0
- package/.claude/skills/gsap-animation/references/scrolltrigger.md +255 -0
- package/.claude/skills/{gsap-timeline/SKILL.md → gsap-animation/references/timeline.md} +7 -19
- package/.claude/skills/gsap-animation/references/utils.md +254 -0
- package/.claude/skills/judgment-day/SKILL.md +19 -1
- package/.claude/skills/kaizen/SKILL.md +1 -0
- package/.claude/skills/nestjs-expert/SKILL.md +8 -0
- package/.claude/skills/product-manager-toolkit/SKILL.md +7 -1
- package/.claude/skills/react-doctor/SKILL.md +6 -0
- package/.claude/skills/seo-audit/SKILL.md +18 -9
- package/.claude/skills/shadcn-ui/SKILL.md +6 -0
- package/.claude/skills/stitch-design/SKILL.md +7 -0
- package/.claude/skills/systematic-debugging/SKILL.md +21 -0
- package/.claude/skills/tailwind-design-system/SKILL.md +8 -0
- package/.claude/skills/ui-ux-pro-max/SKILL.md +21 -0
- package/.claude/skills/vercel-react-best-practices/SKILL.md +3 -0
- package/.claude/templates/implementer.md +6 -0
- package/.claude/templates/leader.md +7 -1
- package/.claude/templates/reviewer.md +6 -0
- package/.claude/templates/tester.md +6 -0
- package/CHANGELOG.md +27 -0
- package/LICENSE +1 -1
- package/README.md +9 -8
- package/bin/akili.js +40 -0
- package/docs/cli.md +1 -1
- package/docs/commands/akili-constitution.md +11 -11
- package/docs/flow.md +20 -0
- package/docs/skills/README.md +34 -31
- package/docs/skills/brainstorming.md +2 -0
- package/docs/skills/cognitive-doc-design.md +2 -0
- package/docs/skills/governance.md +77 -0
- package/docs/skills/gsap-animation.md +29 -0
- package/docs/skills/judgment-day.md +2 -0
- package/docs/skills/product-manager-toolkit.md +1 -1
- package/docs/skills/seo-audit.md +2 -0
- package/docs/skills/systematic-debugging.md +2 -0
- package/docs/skills/ui-ux-pro-max.md +2 -0
- package/package.json +3 -2
- package/.claude/skills/gsap-core/SKILL.md +0 -254
- package/.claude/skills/gsap-frameworks/SKILL.md +0 -153
- package/.claude/skills/gsap-plugins/SKILL.md +0 -426
- package/.claude/skills/gsap-react/SKILL.md +0 -136
- package/.claude/skills/gsap-scrolltrigger/SKILL.md +0 -296
- package/.claude/skills/gsap-utils/SKILL.md +0 -284
- package/docs/skills/gsap-core.md +0 -21
- package/docs/skills/gsap-frameworks.md +0 -20
- package/docs/skills/gsap-performance.md +0 -21
- package/docs/skills/gsap-plugins.md +0 -20
- package/docs/skills/gsap-react.md +0 -22
- package/docs/skills/gsap-scrolltrigger.md +0 -21
- package/docs/skills/gsap-timeline.md +0 -20
- package/docs/skills/gsap-utils.md +0 -21
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# GSAP with Vue, Svelte, and Other Frameworks
|
|
2
|
+
|
|
3
|
+
Read when writing or reviewing GSAP in Vue (or Nuxt), Svelte (or SvelteKit), or other component frameworks with a mounted/unmounted lifecycle. For **React** use `references/react.md` (useGSAP, contextSafe).
|
|
4
|
+
|
|
5
|
+
## Principles (All Frameworks)
|
|
6
|
+
|
|
7
|
+
- **Create** tweens and ScrollTriggers **after** the component's DOM is available (e.g. onMounted, onMount).
|
|
8
|
+
- **Kill or revert** them on **unmount** so nothing runs on detached nodes and there are no leaks.
|
|
9
|
+
- **Scope selectors** to the component root so `.box` matches only elements inside that component.
|
|
10
|
+
|
|
11
|
+
## Vue 3 (Composition API)
|
|
12
|
+
|
|
13
|
+
Use **onMounted** to run GSAP after the component is in the DOM; **onUnmounted** to clean up.
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { onMounted, onUnmounted, ref } from "vue";
|
|
17
|
+
import { gsap } from "gsap";
|
|
18
|
+
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
|
19
|
+
gsap.registerPlugin(ScrollTrigger); // once per app, e.g. in main.js
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
setup() {
|
|
23
|
+
const container = ref(null);
|
|
24
|
+
let ctx;
|
|
25
|
+
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
if (!container.value) return;
|
|
28
|
+
ctx = gsap.context(() => {
|
|
29
|
+
gsap.to(".box", { x: 100, duration: 0.6 });
|
|
30
|
+
gsap.from(".item", { autoAlpha: 0, y: 20, stagger: 0.1 });
|
|
31
|
+
}, container.value);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
onUnmounted(() => {
|
|
35
|
+
ctx?.revert();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return { container };
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- ✅ **gsap.context(callback, scope)** — pass the container ref (`container.value`) so selectors like `.item` are scoped to that root. All animations and ScrollTriggers created inside are tracked and reverted on **ctx.revert()**.
|
|
44
|
+
- ✅ **onUnmounted** — always call **ctx.revert()**.
|
|
45
|
+
|
|
46
|
+
## Vue 3 (script setup)
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
<script setup>
|
|
50
|
+
import { onMounted, onUnmounted, ref } from "vue";
|
|
51
|
+
import { gsap } from "gsap";
|
|
52
|
+
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
|
53
|
+
|
|
54
|
+
const container = ref(null);
|
|
55
|
+
let ctx;
|
|
56
|
+
|
|
57
|
+
onMounted(() => {
|
|
58
|
+
if (!container.value) return;
|
|
59
|
+
ctx = gsap.context(() => {
|
|
60
|
+
gsap.to(".box", { x: 100 });
|
|
61
|
+
gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
|
|
62
|
+
}, container.value);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
onUnmounted(() => {
|
|
66
|
+
ctx?.revert();
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<template>
|
|
71
|
+
<div ref="container">
|
|
72
|
+
<div class="box">Box</div>
|
|
73
|
+
<div class="item">Item</div>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Svelte
|
|
79
|
+
|
|
80
|
+
Use **onMount** to run GSAP after the DOM is ready; return a cleanup that reverts. Svelte 5 uses a different lifecycle, but the principle is the same: create in "mounted", revert in "destroyed".
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
<script>
|
|
84
|
+
import { onMount } from "svelte";
|
|
85
|
+
import { gsap } from "gsap";
|
|
86
|
+
import { ScrollTrigger } from "gsap/ScrollTrigger";
|
|
87
|
+
|
|
88
|
+
let container;
|
|
89
|
+
|
|
90
|
+
onMount(() => {
|
|
91
|
+
if (!container) return;
|
|
92
|
+
const ctx = gsap.context(() => {
|
|
93
|
+
gsap.to(".box", { x: 100 });
|
|
94
|
+
gsap.from(".item", { autoAlpha: 0, stagger: 0.1 });
|
|
95
|
+
}, container);
|
|
96
|
+
return () => ctx.revert();
|
|
97
|
+
});
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<div bind:this={container}>
|
|
101
|
+
<div class="box">Box</div>
|
|
102
|
+
<div class="item">Item</div>
|
|
103
|
+
</div>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
- ✅ **bind:this={container}** — reference the root element to pass to **gsap.context(scope)**.
|
|
107
|
+
- ✅ **return () => ctx.revert()** — onMount's returned cleanup runs when the component is destroyed.
|
|
108
|
+
|
|
109
|
+
## Scoping Selectors
|
|
110
|
+
|
|
111
|
+
Do not use global selectors that can match elements outside the current component. Always pass the **scope** (container element or ref) as the second argument to **gsap.context(callback, scope)**.
|
|
112
|
+
|
|
113
|
+
- ✅ **gsap.context(() => { gsap.to(".box", ...) }, containerRef)** — `.box` is only searched inside `containerRef`.
|
|
114
|
+
- ❌ Running **gsap.to(".box", ...)** without a context scope can affect other instances or the rest of the page.
|
|
115
|
+
|
|
116
|
+
## ScrollTrigger Cleanup
|
|
117
|
+
|
|
118
|
+
ScrollTrigger instances (via the `scrollTrigger` config on a tween/timeline or **ScrollTrigger.create()**) are **included** in **gsap.context()** and reverted on **ctx.revert()**. So:
|
|
119
|
+
|
|
120
|
+
- Create ScrollTriggers inside the same **gsap.context()** callback you use for tweens.
|
|
121
|
+
- Call **ScrollTrigger.refresh()** after layout changes that affect trigger positions — often after DOM updates (nextTick in Vue, tick in Svelte, or after async content load).
|
|
122
|
+
|
|
123
|
+
## When to Create vs Kill
|
|
124
|
+
|
|
125
|
+
| Lifecycle | Action |
|
|
126
|
+
|-----------|--------|
|
|
127
|
+
| **Mounted** | Create tweens and ScrollTriggers inside **gsap.context(scope)**. |
|
|
128
|
+
| **Unmount / Destroy** | Call **ctx.revert()** so all animations and ScrollTriggers in that context are killed and inline styles reverted. |
|
|
129
|
+
|
|
130
|
+
Do not create GSAP animations in setup or a synchronous top-level script that runs before the root element exists. Wait for **onMounted** / **onMount**.
|
|
131
|
+
|
|
132
|
+
## Do Not
|
|
133
|
+
|
|
134
|
+
- ❌ Create tweens or ScrollTriggers before the component is mounted; the DOM nodes may not exist yet.
|
|
135
|
+
- ❌ Use selector strings without a **scope** (pass the container to gsap.context()).
|
|
136
|
+
- ❌ Skip cleanup; always call **ctx.revert()** in onUnmounted / onMount's return.
|
|
137
|
+
- ❌ Register plugins inside a component body that runs every render (wasteful); register once at app level.
|
package/.claude/skills/{gsap-performance/SKILL.md → gsap-animation/references/performance.md}
RENAMED
|
@@ -1,25 +1,15 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: gsap-performance
|
|
3
|
-
description: Official GSAP skill for performance — prefer transforms, avoid layout thrashing, will-change, batching. Use when optimizing GSAP animations, reducing jank, or when the user asks about animation performance, FPS, or smooth 60fps.
|
|
4
|
-
license: MIT
|
|
5
|
-
---
|
|
6
|
-
|
|
7
1
|
# GSAP Performance
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Apply when optimizing GSAP animations for smooth 60fps, reducing layout/paint cost, or when the user asks about performance, jank, or best practices for fast animations.
|
|
12
|
-
|
|
13
|
-
**Related skills:** Build animations with **gsap-core** (transforms, autoAlpha) and **gsap-timeline**; for ScrollTrigger performance see **gsap-scrolltrigger**.
|
|
3
|
+
Read when optimizing GSAP animations for smooth 60fps, reducing jank/dropped frames, avoiding layout thrashing, or when /akili-validate routes a performance issue here.
|
|
14
4
|
|
|
15
5
|
## Prefer Transform and Opacity
|
|
16
6
|
|
|
17
|
-
Animating **transform** (`x`, `y`, `scaleX`, `scaleY`, `rotation`, `rotationX`, `rotationY`, `skewX`, `skewY`) and **opacity** keeps work on the compositor and avoids layout and most paint.
|
|
7
|
+
Animating **transform** (`x`, `y`, `scaleX`, `scaleY`, `rotation`, `rotationX`, `rotationY`, `skewX`, `skewY`) and **opacity** keeps work on the compositor and avoids layout and most paint.
|
|
18
8
|
|
|
19
9
|
- ✅ Prefer: **x**, **y**, **scale**, **rotation**, **opacity**.
|
|
20
10
|
- ❌ Avoid when possible: **width**, **height**, **top**, **left**, **margin**, **padding** (they trigger layout and can cause jank).
|
|
21
11
|
|
|
22
|
-
GSAP
|
|
12
|
+
GSAP's **x** and **y** use transforms (translate) by default; use them instead of **left**/**top** for movement.
|
|
23
13
|
|
|
24
14
|
## will-change
|
|
25
15
|
|
|
@@ -35,13 +25,13 @@ GSAP batches updates internally. When mixing GSAP with direct DOM reads/writes o
|
|
|
35
25
|
|
|
36
26
|
## Many Elements (Stagger, Lists)
|
|
37
27
|
|
|
38
|
-
- Use **stagger** instead of many separate tweens with manual delays when the animation is the same; it
|
|
39
|
-
- For long lists, consider **virtualization** or animating only visible items; avoid
|
|
28
|
+
- Use **stagger** instead of many separate tweens with manual delays when the animation is the same; it's more efficient.
|
|
29
|
+
- For long lists, consider **virtualization** or animating only visible items; avoid hundreds of simultaneous tweens if it causes jank.
|
|
40
30
|
- Reuse timelines where possible; avoid creating new timelines every frame.
|
|
41
31
|
|
|
42
32
|
## Frequently updated properties (e.g. mouse followers)
|
|
43
33
|
|
|
44
|
-
Prefer **gsap.quickTo()** for properties
|
|
34
|
+
Prefer **gsap.quickTo()** for properties updated often (e.g. mouse-follower x/y). It reuses a single tween instead of creating a new one on each update.
|
|
45
35
|
|
|
46
36
|
```javascript
|
|
47
37
|
let xTo = gsap.quickTo("#id", "x", { duration: 0.4, ease: "power3" }),
|
|
@@ -55,13 +45,13 @@ document.querySelector("#container").addEventListener("mousemove", (e) => {
|
|
|
55
45
|
|
|
56
46
|
## ScrollTrigger and Performance
|
|
57
47
|
|
|
58
|
-
- **pin: true** promotes the pinned element; pin only what
|
|
48
|
+
- **pin: true** promotes the pinned element; pin only what's needed.
|
|
59
49
|
- **scrub** with a small value (e.g. `scrub: 1`) can reduce work during scroll; test on low-end devices.
|
|
60
50
|
- Call **ScrollTrigger.refresh()** only when layout actually changes (e.g. after content load), not on every resize; debounce when possible.
|
|
61
51
|
|
|
62
52
|
## Reduce Simultaneous Work
|
|
63
53
|
|
|
64
|
-
- Pause or kill off-screen or inactive animations when
|
|
54
|
+
- Pause or kill off-screen or inactive animations when not visible (e.g. when the user navigates away).
|
|
65
55
|
- Avoid animating huge numbers of properties on many elements at once; simplify or sequence if needed.
|
|
66
56
|
|
|
67
57
|
## Best practices
|
|
@@ -73,7 +63,7 @@ document.querySelector("#container").addEventListener("mousemove", (e) => {
|
|
|
73
63
|
|
|
74
64
|
## Do Not
|
|
75
65
|
|
|
76
|
-
- ❌ Animate **width
|
|
77
|
-
- ❌ Set **will-change** or **force3D** on every element
|
|
66
|
+
- ❌ Animate **width**/**height**/**top**/**left** for movement when **x**/**y**/**scale** can achieve the same look.
|
|
67
|
+
- ❌ Set **will-change** or **force3D** on every element "just in case"; use for elements that are actually animating.
|
|
78
68
|
- ❌ Create hundreds of overlapping tweens or ScrollTriggers without testing on low-end devices.
|
|
79
69
|
- ❌ Ignore cleanup; stray tweens and ScrollTriggers keep running and can hurt performance and correctness.
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# GSAP Plugins
|
|
2
|
+
|
|
3
|
+
Read when using any GSAP plugin: scroll-to, ScrollSmoother, Flip/FLIP, Draggable, Inertia, Observer, SplitText, ScrambleText, DrawSVG, MorphSVG, MotionPath, physics, easing plugins (CustomEase, EasePack, CustomWiggle, CustomBounce), GSDevTools, or Pixi. (ScrollTrigger has its own file: `references/scrolltrigger.md`.)
|
|
4
|
+
|
|
5
|
+
## Registering Plugins
|
|
6
|
+
|
|
7
|
+
Register each plugin once before first use (see SKILL.md for the shared pattern):
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
import gsap from "gsap";
|
|
11
|
+
import { ScrollToPlugin } from "gsap/ScrollToPlugin";
|
|
12
|
+
import { Flip } from "gsap/Flip";
|
|
13
|
+
import { Draggable } from "gsap/Draggable";
|
|
14
|
+
|
|
15
|
+
gsap.registerPlugin(ScrollToPlugin, Flip, Draggable);
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- ✅ Register before using the plugin in any tween or API call.
|
|
19
|
+
- ✅ In React, register at top level or once in the app (before first `useGSAP`); do not register inside a component that re-renders. `useGSAP` is itself a plugin that needs registration.
|
|
20
|
+
|
|
21
|
+
## Scroll
|
|
22
|
+
|
|
23
|
+
### ScrollToPlugin
|
|
24
|
+
|
|
25
|
+
Animates scroll position (window or a scrollable element). Use for "scroll to element/position" without ScrollTrigger.
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
gsap.registerPlugin(ScrollToPlugin);
|
|
29
|
+
|
|
30
|
+
gsap.to(window, { duration: 1, scrollTo: { y: 500 } });
|
|
31
|
+
gsap.to(window, { duration: 1, scrollTo: { y: "#section", offsetY: 50 } });
|
|
32
|
+
gsap.to(scrollContainer, { duration: 1, scrollTo: { x: "max" } });
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| Option | Description |
|
|
36
|
+
|--------|-------------|
|
|
37
|
+
| `x`, `y` | Target scroll position (number), or `"max"` for maximum |
|
|
38
|
+
| `element` | Selector or element to scroll to (scroll-into-view) |
|
|
39
|
+
| `offsetX`, `offsetY` | Offset in pixels from the target position |
|
|
40
|
+
|
|
41
|
+
### ScrollSmoother
|
|
42
|
+
|
|
43
|
+
Smooth scroll wrapper (smooths native scroll). Requires ScrollTrigger and a specific DOM structure. Register after ScrollTrigger.
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<body>
|
|
47
|
+
<div id="smooth-wrapper">
|
|
48
|
+
<div id="smooth-content">
|
|
49
|
+
<!-- ALL YOUR CONTENT HERE -->
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
<!-- position: fixed elements can go outside -->
|
|
53
|
+
</body>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## DOM / UI
|
|
57
|
+
|
|
58
|
+
### Flip
|
|
59
|
+
|
|
60
|
+
Capture state with `Flip.getState()`, change the DOM (layout/classes), then `Flip.from()` animates from the previous state to the new state (FLIP: First, Last, Invert, Play). Use when animating between two layout states (lists, grids, expand/collapse).
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
gsap.registerPlugin(Flip);
|
|
64
|
+
|
|
65
|
+
const state = Flip.getState(".item");
|
|
66
|
+
// change DOM (reorder, add/remove, change classes)
|
|
67
|
+
Flip.from(state, { duration: 0.5, ease: "power2.inOut" });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
| Option | Description |
|
|
71
|
+
|--------|-------------|
|
|
72
|
+
| `absolute` | Use `position: absolute` during the flip (default `false`) |
|
|
73
|
+
| `nested` | When true, only the first level of children is measured (better for nested transforms) |
|
|
74
|
+
| `scale` | When true, scale elements to fit (avoids stretch); default `true` |
|
|
75
|
+
| `simple` | When true, only position/scale animated (faster, less accurate) |
|
|
76
|
+
| `duration`, `ease` | Standard tween options |
|
|
77
|
+
|
|
78
|
+
Docs: https://gsap.com/docs/v3/Plugins/Flip
|
|
79
|
+
|
|
80
|
+
### Draggable
|
|
81
|
+
|
|
82
|
+
Makes elements draggable, spinnable, or throwable. Use for sliders, cards, reorderable lists, or any drag interaction.
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
gsap.registerPlugin(Draggable, InertiaPlugin);
|
|
86
|
+
|
|
87
|
+
Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true });
|
|
88
|
+
Draggable.create(".knob", { type: "rotation" });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Option | Description |
|
|
92
|
+
|--------|-------------|
|
|
93
|
+
| `type` | `"x"`, `"y"`, `"x,y"`, `"rotation"`, `"scroll"` |
|
|
94
|
+
| `bounds` | Element, selector, or `{ minX, maxX, minY, maxY }` to constrain drag |
|
|
95
|
+
| `inertia` | `true` for throw/momentum (requires InertiaPlugin) |
|
|
96
|
+
| `edgeResistance` | 0–1; resistance when dragging past bounds |
|
|
97
|
+
| `cursor` | CSS cursor during drag |
|
|
98
|
+
| `onDragStart`, `onDrag`, `onDragEnd` | Callbacks; receive event and target |
|
|
99
|
+
| `onThrowUpdate`, `onThrowComplete` | Callbacks when inertia is active |
|
|
100
|
+
|
|
101
|
+
### Inertia (InertiaPlugin)
|
|
102
|
+
|
|
103
|
+
Works with Draggable for momentum after release, or tracks the velocity of any property so it can glide to a stop. Register with Draggable when using `inertia: true`:
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
gsap.registerPlugin(Draggable, InertiaPlugin);
|
|
107
|
+
Draggable.create(".box", { type: "x,y", inertia: true });
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Track velocity of a property, then use `"auto"` to continue current velocity and glide to a stop:
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
InertiaPlugin.track(".box", "x");
|
|
114
|
+
gsap.to(obj, { inertia: { x: "auto" } });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Observer
|
|
118
|
+
|
|
119
|
+
Normalizes pointer and scroll input across devices. Use for swipe, scroll direction, or custom gesture logic without tying to scroll position.
|
|
120
|
+
|
|
121
|
+
```javascript
|
|
122
|
+
gsap.registerPlugin(Observer);
|
|
123
|
+
|
|
124
|
+
Observer.create({
|
|
125
|
+
target: "#area",
|
|
126
|
+
onUp: () => {},
|
|
127
|
+
onDown: () => {},
|
|
128
|
+
onLeft: () => {},
|
|
129
|
+
onRight: () => {},
|
|
130
|
+
tolerance: 10
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
| Option | Description |
|
|
135
|
+
|--------|-------------|
|
|
136
|
+
| `target` | Element or selector to observe |
|
|
137
|
+
| `onUp`, `onDown`, `onLeft`, `onRight` | Callbacks when swipe/scroll passes tolerance in that direction |
|
|
138
|
+
| `tolerance` | Pixels before direction is detected; default 10 |
|
|
139
|
+
| `type` | `"touch"`, `"pointer"`, or `"wheel"` (default `"touch,pointer"`) |
|
|
140
|
+
|
|
141
|
+
## Text
|
|
142
|
+
|
|
143
|
+
### SplitText
|
|
144
|
+
|
|
145
|
+
Splits an element's text into characters, words, and/or lines (each in its own element) for staggered animation. Returns an instance with **chars**, **words**, **lines** (and **masks** when `mask` is set). Restore original markup with **revert()** or let **gsap.context()** revert. Integrates with **gsap.context()**, **matchMedia()**, and **useGSAP()**. API: **SplitText.create(target, vars)**.
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
gsap.registerPlugin(SplitText);
|
|
149
|
+
|
|
150
|
+
const split = SplitText.create(".heading", { type: "words, chars" });
|
|
151
|
+
gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.03, duration: 0.4 });
|
|
152
|
+
// later: split.revert() or let gsap.context() cleanup revert
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
With **onSplit()** (3.13.0+), animations run on each split and on re-split when **autoSplit** is used; returning a tween/timeline from **onSplit()** lets SplitText clean up and sync progress on re-split:
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
SplitText.create(".split", {
|
|
159
|
+
type: "lines",
|
|
160
|
+
autoSplit: true,
|
|
161
|
+
onSplit(self) {
|
|
162
|
+
return gsap.from(self.lines, { y: 100, opacity: 0, stagger: 0.05, duration: 0.5 });
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| Option | Description |
|
|
168
|
+
|--------|-------------|
|
|
169
|
+
| **type** | Comma-separated: `"chars"`, `"words"`, `"lines"`. Default `"chars,words,lines"`. Split only what's needed for performance. Avoid chars-only without words/lines, or use **smartWrap: true**. |
|
|
170
|
+
| **charsClass**, **wordsClass**, **linesClass** | CSS class on each split element. Append `"++"` for an incremented class (e.g. `linesClass: "line++"` → `line1`, `line2`, …). |
|
|
171
|
+
| **aria** | `"auto"` (default), `"hidden"`, or `"none"`. `"auto"` adds `aria-label` on the element and `aria-hidden` on split units; `"hidden"` hides all from readers; `"none"` leaves aria unchanged. |
|
|
172
|
+
| **autoSplit** | When `true`, reverts and re-splits when fonts load or element width changes (lines split), avoiding wrong line breaks. **Animations must be created inside onSplit()**; **return** the animation for automatic cleanup and time-sync on re-split. |
|
|
173
|
+
| **onSplit(self)** | Callback when split completes (and on each re-split if **autoSplit**). Returning a tween/timeline enables automatic revert/sync on re-split. |
|
|
174
|
+
| **mask** | `"lines"`, `"words"`, or `"chars"`. Wraps each unit with `overflow: clip` for mask/reveal effects. Access wrappers on the instance's **masks** array. |
|
|
175
|
+
| **tag** | Wrapper tag; default `"div"`. Use `"span"` for inline (transforms like rotation/scale may not render on inline elements in some browsers). |
|
|
176
|
+
| **deepSlice** | When `true` (default), nested elements spanning multiple lines are subdivided so lines don't stretch vertically. Line-splitting only. |
|
|
177
|
+
| **ignore** | Selector or element(s) to leave unsplit (e.g. `ignore: "sup"`). |
|
|
178
|
+
| **smartWrap** | When splitting **chars** only, wraps words in `white-space: nowrap` to avoid mid-word breaks. Ignored if words/lines are split. Default `false`. |
|
|
179
|
+
| **wordDelimiter** | Word boundary: string (default `" "`), RegExp, or `{ delimiter: RegExp, replaceWith: string }`. |
|
|
180
|
+
| **prepareText(text, parent)** | Function returning modified text before splitting (e.g. insert break markers for languages without spaces). |
|
|
181
|
+
| **propIndex** | When `true`, adds a CSS variable with index on each split element (`--word: 1`, `--char: 2`). |
|
|
182
|
+
| **reduceWhiteSpace** | Collapse consecutive spaces; default `true`. From 3.13.0 also honors line breaks / `<pre>`. |
|
|
183
|
+
| **onRevert** | Callback when the instance is reverted. |
|
|
184
|
+
|
|
185
|
+
**Tips:** Split only what is animated. For custom fonts, split after they load (`document.fonts.ready.then(...)`) or use **autoSplit: true** with **onSplit()**. To avoid kerning shift when splitting chars, use CSS `font-kerning: none; text-rendering: optimizeSpeed;`. Avoid `text-wrap: balance`. SplitText does not support SVG `<text>`.
|
|
186
|
+
|
|
187
|
+
Docs: [SplitText](https://gsap.com/docs/v3/Plugins/SplitText/)
|
|
188
|
+
|
|
189
|
+
### ScrambleText
|
|
190
|
+
|
|
191
|
+
Animates text with a scramble/glitch effect.
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
gsap.registerPlugin(ScrambleTextPlugin);
|
|
195
|
+
|
|
196
|
+
gsap.to(".text", {
|
|
197
|
+
duration: 1,
|
|
198
|
+
scrambleText: { text: "New message", chars: "01", revealDelay: 0.5 }
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## SVG
|
|
203
|
+
|
|
204
|
+
### DrawSVG (DrawSVGPlugin)
|
|
205
|
+
|
|
206
|
+
Reveals/hides the stroke of SVG elements by animating `stroke-dashoffset` / `stroke-dasharray`. Works on `<path>`, `<line>`, `<polyline>`, `<polygon>`, `<rect>`, `<ellipse>`. Use for "drawing"/"erasing" strokes.
|
|
207
|
+
|
|
208
|
+
**drawSVG value:** Describes the **visible segment** of the stroke (`"start end"` in percent or length), not "A to B over time." `"0% 100%"` = full stroke; `"20% 80%"` = stroke only between 20% and 80%. The tween animates from the element's **current** segment to the **target** segment. Single value (e.g. `0`, `"100%"`) means start is 0.
|
|
209
|
+
|
|
210
|
+
**Required:** The element must have a visible stroke (`stroke` + `stroke-width`), else nothing draws.
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
gsap.registerPlugin(DrawSVGPlugin);
|
|
214
|
+
|
|
215
|
+
gsap.from("#path", { duration: 1, drawSVG: 0 }); // nothing → full stroke
|
|
216
|
+
gsap.fromTo("#path", { drawSVG: "0% 0%" }, { drawSVG: "0% 100%", duration: 1 });
|
|
217
|
+
gsap.to("#path", { duration: 1, drawSVG: "20% 80%" }); // middle only
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Caveats:** Only affects stroke (not fill). Prefer single-segment `<path>` elements. Contents of `<use>` cannot be visually changed. **DrawSVGPlugin.getLength(element)** and **DrawSVGPlugin.getPosition(element)** return stroke length/position.
|
|
221
|
+
|
|
222
|
+
Docs: [DrawSVG](https://gsap.com/docs/v3/Plugins/DrawSVGPlugin)
|
|
223
|
+
|
|
224
|
+
### MorphSVG (MorphSVGPlugin)
|
|
225
|
+
|
|
226
|
+
Morphs one SVG shape into another by animating the `d` attribute. Start/end shapes need not share point counts. Works on `<path>`, `<polyline>`, `<polygon>`; primitives are converted internally or via **MorphSVGPlugin.convertToPath()**.
|
|
227
|
+
|
|
228
|
+
**morphSVG value:** a **selector**, **element**, **raw path data**, or (for polygon/polyline) a **points string**. Full config uses the **object form** with **shape** required.
|
|
229
|
+
|
|
230
|
+
```javascript
|
|
231
|
+
gsap.registerPlugin(MorphSVGPlugin);
|
|
232
|
+
|
|
233
|
+
MorphSVGPlugin.convertToPath("circle, rect, ellipse, line"); // if needed
|
|
234
|
+
|
|
235
|
+
gsap.to("#diamond", { duration: 1, morphSVG: "#lightning", ease: "power2.inOut" });
|
|
236
|
+
gsap.to("#diamond", {
|
|
237
|
+
duration: 1,
|
|
238
|
+
morphSVG: { shape: "#lightning", type: "rotational", shapeIndex: 2 }
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
| Option | Description |
|
|
243
|
+
|--------|-------------|
|
|
244
|
+
| **shape** | _(Required.)_ Target shape: selector, element, or raw path string. |
|
|
245
|
+
| **type** | `"linear"` (default) or `"rotational"`. Rotational uses angle/length interpolation and can avoid mid-morph kinks. |
|
|
246
|
+
| **map** | Segment matching: `"size"` (default), `"position"`, or `"complexity"`. |
|
|
247
|
+
| **shapeIndex** | Offsets which start point maps to the first end point (avoids crossing/inverting). Number for single-segment; **array** for multi-segment (negative reverses that segment). Use **shapeIndex: "log"** once to log the auto value; **findShapeIndex(start, end)** gives an interactive UI. Closed paths only. |
|
|
248
|
+
| **smooth** | (3.14+). Smoothing points. Number, `"auto"`, or object `{ points, redraw, persist }`. `redraw: false` keeps original anchors; `persist: false` removes added points on end. |
|
|
249
|
+
| **curveMode** | Boolean (3.14+). Interpolates control-handle angle/length instead of raw x/y to avoid kinks. |
|
|
250
|
+
| **origin** | Rotation origin for **type: "rotational"**. `"50% 50%"` (default) or `"20% 60%, 35% 90%"` for different start/end origins. |
|
|
251
|
+
| **precision** | Decimal places for output path data; default `2`. |
|
|
252
|
+
| **precompile** | Array of precomputed path strings (or `"log"` once, copy from console). Skips startup calc for complex morphs; `<path>` only. |
|
|
253
|
+
| **render** | Function(rawPath, target) each update — e.g. draw to canvas. |
|
|
254
|
+
| **updateTarget** | Set `false` (with **render**, e.g. canvas-only) so the original `<path>` isn't updated. |
|
|
255
|
+
|
|
256
|
+
**Utilities:** **convertToPath(selector | element)**, **rawPathToString(rawPath)**, **stringToRawPath(d)**. The plugin stores the original `d` for tweening back.
|
|
257
|
+
|
|
258
|
+
**Tips:** For twisted/inverted morphs set **shapeIndex** (`"log"` or findShapeIndex()). Precompile only when the first frame is slow; it doesn't fix jank during the tween.
|
|
259
|
+
|
|
260
|
+
Docs: [MorphSVG](https://gsap.com/docs/v3/Plugins/MorphSVGPlugin)
|
|
261
|
+
|
|
262
|
+
### MotionPath (MotionPathPlugin)
|
|
263
|
+
|
|
264
|
+
Animates an element along an SVG path.
|
|
265
|
+
|
|
266
|
+
```javascript
|
|
267
|
+
gsap.registerPlugin(MotionPathPlugin);
|
|
268
|
+
|
|
269
|
+
gsap.to(".dot", {
|
|
270
|
+
duration: 2,
|
|
271
|
+
motionPath: { path: "#path", align: "#path", alignOrigin: [0.5, 0.5] }
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
| Option | Description |
|
|
276
|
+
|--------|-------------|
|
|
277
|
+
| `path` | SVG path element, selector, or path data string |
|
|
278
|
+
| `align` | Path element or selector to align the target to |
|
|
279
|
+
| `alignOrigin` | `[x, y]` origin (0–1); default `[0.5, 0.5]` |
|
|
280
|
+
| `autoRotate` | Rotate element to follow path tangent |
|
|
281
|
+
| `curviness` | 0–2; path smoothing |
|
|
282
|
+
|
|
283
|
+
### MotionPathHelper
|
|
284
|
+
|
|
285
|
+
Visual editor for MotionPath (alignment, offset). Development only.
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
gsap.registerPlugin(MotionPathPlugin, MotionPathHelperPlugin);
|
|
289
|
+
|
|
290
|
+
const helper = MotionPathHelper.create(".dot", "#path", { end: 0.5 });
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Easing
|
|
294
|
+
|
|
295
|
+
### CustomEase
|
|
296
|
+
|
|
297
|
+
Custom easing curves (cubic-bezier or SVG path) — use when a built-in ease is not enough. Register when using:
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
gsap.registerPlugin(CustomEase);
|
|
301
|
+
|
|
302
|
+
// Simple cubic-bezier (same values as CSS cubic-bezier())
|
|
303
|
+
const myEase = CustomEase.create("my-ease", ".17,.67,.83,.67");
|
|
304
|
+
gsap.to(".item", { x: 100, ease: myEase, duration: 1 });
|
|
305
|
+
|
|
306
|
+
// Complex curve with any number of control points, as normalized SVG path data
|
|
307
|
+
const hop = CustomEase.create("hop", "M0,0 C0,0 0.056,0.442 0.175,0.442 0.294,0.442 0.332,0 0.332,0 0.332,0 0.414,1 0.671,1 0.991,1 1,0 1,0");
|
|
308
|
+
gsap.to(".item", { x: 100, ease: hop, duration: 1 });
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### EasePack
|
|
312
|
+
|
|
313
|
+
Adds more named eases (SlowMo, RoughEase, ExpoScaleEase). Register and use by name in tweens.
|
|
314
|
+
|
|
315
|
+
### CustomWiggle
|
|
316
|
+
|
|
317
|
+
Wiggle/shake easing — a value oscillates multiple times.
|
|
318
|
+
|
|
319
|
+
### CustomBounce
|
|
320
|
+
|
|
321
|
+
Bounce-style easing with configurable strength.
|
|
322
|
+
|
|
323
|
+
## Physics
|
|
324
|
+
|
|
325
|
+
### Physics2D (Physics2DPlugin)
|
|
326
|
+
|
|
327
|
+
2D physics (velocity, angle, gravity). Use for projectiles, bouncing.
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
gsap.registerPlugin(Physics2DPlugin);
|
|
331
|
+
|
|
332
|
+
gsap.to(".ball", {
|
|
333
|
+
duration: 2,
|
|
334
|
+
physics2D: { velocity: 250, angle: 80, gravity: 500 }
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### PhysicsProps (PhysicsPropsPlugin)
|
|
339
|
+
|
|
340
|
+
Applies physics to property values.
|
|
341
|
+
|
|
342
|
+
```javascript
|
|
343
|
+
gsap.registerPlugin(PhysicsPropsPlugin);
|
|
344
|
+
|
|
345
|
+
gsap.to(".obj", {
|
|
346
|
+
duration: 2,
|
|
347
|
+
physicsProps: {
|
|
348
|
+
x: { velocity: 100, end: 300 },
|
|
349
|
+
y: { velocity: -50, acceleration: 200 }
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Development
|
|
355
|
+
|
|
356
|
+
### GSDevTools
|
|
357
|
+
|
|
358
|
+
UI for scrubbing timelines, toggling, and debugging. **Development only — do not ship.**
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
gsap.registerPlugin(GSDevTools);
|
|
362
|
+
GSDevTools.create({ animation: tl });
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Other
|
|
366
|
+
|
|
367
|
+
### Pixi (PixiPlugin)
|
|
368
|
+
|
|
369
|
+
Integrates GSAP with PixiJS for animating Pixi display objects.
|
|
370
|
+
|
|
371
|
+
```javascript
|
|
372
|
+
gsap.registerPlugin(PixiPlugin);
|
|
373
|
+
|
|
374
|
+
const sprite = new PIXI.Sprite(texture);
|
|
375
|
+
gsap.to(sprite, { pixi: { x: 200, y: 100, scale: 1.5 }, duration: 1 });
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Best practices
|
|
379
|
+
|
|
380
|
+
- ✅ Register every plugin used with **gsap.registerPlugin()** before first use.
|
|
381
|
+
- ✅ Use **Flip.getState()** → DOM change → **Flip.from()** for layout transitions; use **Draggable** + **InertiaPlugin** for drag with momentum.
|
|
382
|
+
- ✅ Revert plugin instances (e.g. `splitInstance.revert()`) when components unmount or elements are removed.
|
|
383
|
+
|
|
384
|
+
## Do Not
|
|
385
|
+
|
|
386
|
+
- ❌ Use a plugin in a tween or API without registering it first.
|
|
387
|
+
- ❌ Ship GSDevTools or development-only plugins to production.
|
|
388
|
+
|
|
389
|
+
### Learn More
|
|
390
|
+
https://gsap.com/docs/v3/Plugins/
|