@skilly-hand/skilly-hand 0.26.0 → 0.26.2

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +2 -0
  3. package/catalog/README.md +3 -1
  4. package/catalog/catalog-index.json +2 -0
  5. package/catalog/skills/frontend-design/SKILL.md +22 -11
  6. package/catalog/skills/frontend-design/agents/critique.md +190 -0
  7. package/catalog/skills/frontend-design/agents/motion-designer.md +35 -1
  8. package/catalog/skills/frontend-design/manifest.json +17 -8
  9. package/catalog/skills/gsap-animation/SKILL.md +149 -0
  10. package/catalog/skills/gsap-animation/manifest.json +30 -0
  11. package/catalog/skills/gsap-animation/references/core-patterns.md +61 -0
  12. package/catalog/skills/gsap-animation/references/official-source-map.md +31 -0
  13. package/catalog/skills/gsap-animation/references/performance-accessibility.md +61 -0
  14. package/catalog/skills/gsap-animation/references/plugin-selection.md +42 -0
  15. package/catalog/skills/gsap-animation/references/react-patterns.md +59 -0
  16. package/catalog/skills/gsap-animation/references/scrolltrigger-patterns.md +61 -0
  17. package/catalog/skills/motion-animation/SKILL.md +148 -0
  18. package/catalog/skills/motion-animation/manifest.json +28 -0
  19. package/catalog/skills/motion-animation/references/js-patterns.md +81 -0
  20. package/catalog/skills/motion-animation/references/official-source-map.md +32 -0
  21. package/catalog/skills/motion-animation/references/performance-accessibility.md +49 -0
  22. package/catalog/skills/motion-animation/references/react-patterns.md +86 -0
  23. package/package.json +1 -1
  24. package/packages/catalog/package.json +1 -1
  25. package/packages/cli/package.json +1 -1
  26. package/packages/core/package.json +1 -1
  27. package/packages/core/src/index.js +25 -2
  28. package/packages/detectors/package.json +1 -1
  29. package/packages/detectors/src/index.js +9 -0
@@ -0,0 +1,86 @@
1
+ # Motion React Patterns
2
+
3
+ Extracted: 2026-05-03
4
+
5
+ Sources:
6
+
7
+ - https://motion.dev/docs/react
8
+ - https://motion.dev/docs/react-motion-component
9
+ - https://motion.dev/docs/react-animate-presence
10
+ - https://motion.dev/docs/react-use-scroll
11
+ - https://motion.dev/docs/react-use-reduced-motion
12
+
13
+ ## Selection
14
+
15
+ Use Motion for React when a React project already uses Motion/Framer Motion, when animation should be expressed through component props, or when the desired behavior is gestures, exit animation, layout animation, scroll animation, or SVG animation in React.
16
+
17
+ Use JavaScript patterns from [js-patterns.md](js-patterns.md) for framework-agnostic utilities. Use `gsap-animation` when the project requires GSAP-specific timelines, ScrollTrigger behavior, plugins, or existing GSAP conventions.
18
+
19
+ ## Installation and Imports
20
+
21
+ Motion for React uses the same package:
22
+
23
+ ```bash
24
+ npm install motion
25
+ ```
26
+
27
+ Import React APIs from `"motion/react"`:
28
+
29
+ ```tsx
30
+ import { motion } from "motion/react";
31
+ ```
32
+
33
+ Ask before adding `motion` when it is not already present.
34
+
35
+ ## motion Components
36
+
37
+ Use `motion` components for animating HTML and SVG elements with props:
38
+
39
+ - `initial` defines the starting visual state.
40
+ - `animate` defines the current target visual state.
41
+ - `transition` defines duration, easing, spring, and related transition behavior.
42
+ - Variants can coordinate named states across parent/child component trees.
43
+
44
+ Use `motion.create()` for custom components only when the official component integration pattern is needed.
45
+
46
+ ## Gestures
47
+
48
+ Use React gesture props for interaction feedback:
49
+
50
+ - `whileHover` for hover targets.
51
+ - `whileTap` for press/tap targets.
52
+ - Hover, tap, focus, and drag are supported gesture categories in the React quick start.
53
+
54
+ Keep gesture motion brief and meaningful, and pair it with accessible non-motion feedback when needed.
55
+
56
+ ## Scroll Animation
57
+
58
+ Use `whileInView` for scroll-triggered animation when an element should animate as it enters or leaves the viewport.
59
+
60
+ Use `useScroll()` when a MotionValue should be linked directly to scroll progress, such as a progress bar scale.
61
+
62
+ ## Layout Animation
63
+
64
+ Use `layout` when React layout changes in size, position, or reorder should animate smoothly.
65
+
66
+ Use `layoutId` for shared layout transitions between different elements.
67
+
68
+ When mixing layout animation with exits, consider official `AnimatePresence` mode guidance and `LayoutGroup` guidance if surrounding components need coordinated layout updates.
69
+
70
+ ## Exit Animation
71
+
72
+ Use `AnimatePresence` when removed React elements should animate out before leaving the DOM:
73
+
74
+ - Place the conditional child inside `AnimatePresence`; do not unmount `AnimatePresence` at the same time as the child.
75
+ - Give every direct child a stable unique `key`.
76
+ - Use the `exit` prop on `motion` components.
77
+ - Use `mode="wait"` only for one child at a time.
78
+ - Use `mode="popLayout"` carefully with positioned parents and forwarded refs for custom immediate children.
79
+
80
+ ## SVG Animation
81
+
82
+ Motion for React supports SVG animation. Use `motion` SVG elements and official SVG props such as `pathLength` for path drawing effects where appropriate.
83
+
84
+ ## React Server Components
85
+
86
+ In React Server Component projects, components that use Motion runtime behavior must be client components. Keep Motion imports and animated components in client-side files.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/skilly-hand",
3
- "version": "0.26.0",
3
+ "version": "0.26.2",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/catalog",
3
- "version": "0.26.0",
3
+ "version": "0.26.2",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/cli",
3
- "version": "0.26.0",
3
+ "version": "0.26.2",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/core",
3
- "version": "0.26.0",
3
+ "version": "0.26.2",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -269,6 +269,26 @@ function parseSkillIds(input) {
269
269
  return uniq((input || []).flatMap((value) => String(value).split(",")).map((value) => value.trim()).filter(Boolean));
270
270
  }
271
271
 
272
+ function expandSkillDependencies({ catalog, skillIds }) {
273
+ const byId = new Map(catalog.filter((skill) => skill.portable).map((skill) => [skill.id, skill]));
274
+ const expanded = new Set(skillIds);
275
+ const pending = [...skillIds];
276
+
277
+ while (pending.length > 0) {
278
+ const skillId = pending.pop();
279
+ const skill = byId.get(skillId);
280
+ if (!skill || !Array.isArray(skill.dependencies)) continue;
281
+
282
+ for (const dependencyId of skill.dependencies) {
283
+ if (!byId.has(dependencyId) || expanded.has(dependencyId)) continue;
284
+ expanded.add(dependencyId);
285
+ pending.push(dependencyId);
286
+ }
287
+ }
288
+
289
+ return expanded;
290
+ }
291
+
272
292
  export function resolveSkillSelectionByIds({ catalog, selectedSkillIds = [] }) {
273
293
  const ids = parseSkillIds(selectedSkillIds);
274
294
  const portableById = new Map(
@@ -293,7 +313,9 @@ export function resolveSkillSelectionByIds({ catalog, selectedSkillIds = [] }) {
293
313
  throw new Error(invalid.join("; "));
294
314
  }
295
315
 
296
- return ids.map((id) => portableById.get(id)).sort((a, b) => a.id.localeCompare(b.id));
316
+ const expanded = expandSkillDependencies({ catalog, skillIds: ids });
317
+
318
+ return [...expanded].map((id) => portableById.get(id)).sort((a, b) => a.id.localeCompare(b.id));
297
319
  }
298
320
 
299
321
  export function resolveSkillSelection({ catalog, detections, includeTags = [], excludeTags = [] }) {
@@ -306,7 +328,8 @@ export function resolveSkillSelection({ catalog, detections, includeTags = [], e
306
328
  }
307
329
  }
308
330
 
309
- let selected = catalog.filter((skill) => requested.has(skill.id) && skill.portable);
331
+ const expanded = expandSkillDependencies({ catalog, skillIds: [...requested] });
332
+ let selected = catalog.filter((skill) => expanded.has(skill.id) && skill.portable);
310
333
 
311
334
  if (includeTags.length > 0) {
312
335
  selected = selected.filter((skill) => includeTags.every((tag) => skill.tags.includes(tag)));
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/detectors",
3
- "version": "0.26.0",
3
+ "version": "0.26.2",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -187,6 +187,15 @@ export async function detectProject(cwd) {
187
187
  });
188
188
  }
189
189
 
190
+ if ("gsap" in deps || "@gsap/react" in deps) {
191
+ addDetection(results, {
192
+ technology: "gsap",
193
+ confidence: 0.95,
194
+ reasons: ['Dependency "gsap" or "@gsap/react" found in package.json'],
195
+ recommendedSkillIds: ["gsap-animation"]
196
+ });
197
+ }
198
+
190
199
  return results.sort((a, b) => b.confidence - a.confidence || a.technology.localeCompare(b.technology));
191
200
  }
192
201