
Morphing Icons
Implement animated icon components that morph between any two glyphs using a shared three-line SVG model.
Install
npx skills add https://github.com/raphaelsalaja/skill --skill morphing-iconsWhat is this skill?
- Every icon uses exactly three SVG lines so any icon can morph into any other
- Collapsed center-point lines hide unused strokes in simpler glyphs
- IconDefinition includes optional rotation and rotation groups for coordinated transforms
- Shape transformation instead of opacity crossfades for crisp motion
- 14×14 viewbox convention with typed IconLine coordinates
Adoption & trust: 1 installs on skills.sh; 18 GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
Recommended Skills
Frontend Designanthropics/skills
Vercel React Best Practicesvercel-labs/agent-skills
Remotion Best Practicesremotion-dev/skills
Vercel Composition Patternsvercel-labs/agent-skills
Develop Userscriptsxixu-me/skills
Next Best Practicesvercel-labs/next-skills
Journey fit
Common Questions / FAQ
Is Morphing Icons safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Morphing Icons
# Morphing Icons Build icons that transform through actual shape transformation, not crossfades. Any icon can morph into any other because they share the same underlying 3-line structure. ## Core Concept Every icon is composed of exactly **three SVG lines**. Icons that need fewer lines collapse the extras to invisible center points. This constraint enables seamless morphing between any two icons. ## Architecture ### 1. Line Definition Each line has coordinates and optional opacity: ```ts interface IconLine { x1: number; y1: number; x2: number; y2: number; opacity?: number; } ``` ### 2. Collapsed Lines Icons needing fewer than 3 lines use collapsed lines—zero-length lines at the center: ```ts const CENTER = 7; // Center of 14x14 viewbox const collapsed: IconLine = { x1: CENTER, y1: CENTER, x2: CENTER, y2: CENTER, opacity: 0, }; ``` ### 3. Icon Definition Each icon has exactly 3 lines, optional rotation, and optional group: ```ts interface IconDefinition { lines: [IconLine, IconLine, IconLine]; rotation?: number; group?: string; } ``` ### 4. Rotation Groups Icons sharing a `group` animate rotation when transitioning between them. Icons without matching groups jump to the new rotation instantly: ```ts // These rotate smoothly between each other { lines: plusLines, rotation: 0, group: "plus-cross" } // plus { lines: plusLines, rotation: 45, group: "plus-cross" } // cross // These rotate smoothly between each other { lines: arrowLines, rotation: 0, group: "arrow" } // arrow-right { lines: arrowLines, rotation: 90, group: "arrow" } // arrow-down { lines: arrowLines, rotation: 180, group: "arrow" } // arrow-left { lines: arrowLines, rotation: -90, group: "arrow" } // arrow-up ``` ## Implementation Rules ### `morphing-three-lines` Every icon MUST use exactly 3 lines. No more, no fewer. **Fail:** ```ts const checkIcon = { lines: [ { x1: 2, y1: 7.5, x2: 5.5, y2: 11 }, { x1: 5.5, y1: 11, x2: 12, y2: 3 }, ], // Only 2 lines }; ``` **Pass:** ```ts const checkIcon = { lines: [ { x1: 2, y1: 7.5, x2: 5.5, y2: 11 }, { x1: 5.5, y1: 11, x2: 12, y2: 3 }, collapsed, // Third line collapsed ], }; ``` ### `morphing-use-collapsed` Unused lines must use the collapsed constant, not omission or null. **Fail:** ```ts const minusIcon = { lines: [ { x1: 2, y1: 7, x2: 12, y2: 7 }, null, null, ], }; ``` **Pass:** ```ts const minusIcon = { lines: [ { x1: 2, y1: 7, x2: 12, y2: 7 }, collapsed, collapsed, ], }; ``` ### `morphing-consistent-viewbox` All icons must use the same viewBox (14x14 recommended). **Fail:** ```ts // Mixing viewbox scales const icon1 = { lines: [{ x1: 2, y1: 7, x2: 12, y2: 7 }, ...] }; // 14x14 const icon2 = { lines: [{ x1: 4, y1: 14, x2: 24, y2: 14 }, ...] }; // 28x28 ``` **Pass:** ```ts const VIEWBOX_SIZE = 14; const CENTER = 7; // All coordinates within 0-14 range ``` ### `morphing-group-variants` Icons that are rotational variants MUST share the same group and base lines. **Fail:** ```ts // Different line definitions for arrows const arrowRight = { lines: [{ x1: 2, y1: 7, x2: 12, y2: 7 }, ...] }; const arrowDown = { lines: [{ x1: 7, y1: 2, x2: 7, y2: 12 }, ...] }; // Different! ``` **Pass:** ```ts const arrowLines: [IconLine, IconLine, IconLine] = [ { x1: 2, y1: 7, x2: 12, y2: 7 }, { x1: 7.5, y1: 2.5, x2: 12, y2: 7 }, { x1: 7.5, y1: 11.5, x2: 12, y2: 7 }, ]; const icons = { "arrow-right": { lines: arrowLines, rotation: 0, group: "arrow" }, "arrow-down": { lines: arrowLines, rotation: 90, group: "arrow" }, "arrow-left": { lines: arr