<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/morphicons-any-stroke-icon-morphs-into-any-other-qpdg4dbpn" -->

---
title: morphicons: any stroke icon morphs into any other
description: morphicons is a React library for animating icon transitions using Procrustes-based optimal 2D similarity solving and polar-space interpolation. It requires no...
canonical: https://daily.dev/posts/morphicons-any-stroke-icon-morphs-into-any-other-qpdg4dbpn
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: morphicons: any stroke icon morphs into any other | daily.dev
og:description: morphicons is a React library for animating icon transitions using Procrustes-based optimal 2D similarity solving and polar-space interpolation. It requires no...
og:url: https://daily.dev/posts/morphicons-any-stroke-icon-morphs-into-any-other-qpdg4dbpn
og:image: https://api.daily.dev/og/posts/QpDg4dbpN.png
og:image:alt: morphicons: any stroke icon morphs into any other
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# morphicons: any stroke icon morphs into any other

**[WebDev](https://daily.dev/sources/webdev)** · [@guillermolg](https://daily.dev/guillermolg) · 2 min read · 149 upvotes · 12 comments

## Summary

morphicons is a React library for animating icon transitions using Procrustes-based optimal 2D similarity solving and polar-space interpolation. It requires no per-pair configuration — rotations emerge automatically (e.g., arrow-right to arrow-down yields 90°, plus to X yields 45°). The API is a single prop change on a MorphIcon component, with three modes: uncontrolled, controlled (for gestures/scroll), and imperative via ref. Features include real mid-flight interruption with velocity preservation, clean SSR with zero flash, drop-in Lucide compatibility, accessibility support, and prefers-reduced-motion handling. Works with Lucide, Tabler, Heroicons, Iconoir, and shadcn icons. MIT licensed, zero runtime deps, 7.65 KB gzipped.

## Content

[morphicons](https://www.morphicons.com)
I got tired of icon morphs that either need a hand-declared "rotation group" per pair, or interpolate raw coordinates and shear the shape in transit. So I built morphicons.

The whole API is: change the prop.

```
import { MorphIcon } from "morphicons/react";
import { Menu, X } from "lucide"; // data, not components

<button onClick={() => setOpen(o => !o)} aria-expanded={open}>
  <MorphIcon icon={open ? X : Menu} />
</button>
```

No wrappers, no `AnimatePresence`, no keys, no from/to pairs, no config. State lives outside; the animation is an implementation detail the component picks up when the prop changes.

Three modes if you need them: uncontrolled (above), controlled (`from`/`to` + `progress`, for gestures/scroll) and imperative (`ref.morphTo()` / `ref.set()`).

What I actually care about:

- **Rotations emerge.** It solves the optimal 2D similarity between the two shapes (Procrustes) and interpolates in polar space. arrow-right → arrow-down gives θ = 90° on its own. plus → x gives 45°. Nobody declares that anywhere.
- **Real interruptions.** A `morphTo` mid-flight re-plans from the current intermediate shape and preserves the spring's velocity. Click spam never jumps.
- **Clean SSR.** The server emits the exact static SVG — zero flash, zero layout shift. The runtime is born on hydration.
- **Drop-in for lucide-react**: `size`, `strokeWidth`, `absoluteStrokeWidth`, `color`, `className` and the rest of the svg props pass through. `aria-hidden` by default, `label` → `role="img"` + `<title>`. `prefers-reduced-motion` degrades to an instant swap.
- One global rAF for every instance on the page.

Works with Lucide, Tabler, Heroicons (outline), Iconoir and the shadcn icon registry — no per-library adapters, because it just eats a `d` string or Lucide's `[tag, attrs][]` shape. Requirement is that the icons are stroke-drawn on a shared grid (all of the above are 24×24); off-grid packs go through `fitIcon(icon, 32)` once at module scope.

MIT, zero runtime deps, ESM, 7.65 KB gzip for the React entry (react external). React >= 18 as optional peer.

Playground with a scrubber so you can freeze any morph mid-flight: https://www.morphicons.com

Repo: https://github.com/guillermolg00/morphicons

## Community discussion

Top comments from developers on daily.dev.

**@feforeboot** · 3 upvotes

> Incredibly cool.

**@sevensolutions** · 2 upvotes

> This looks very cool 😁. Think iam gonna use it some day but please also add Vue support.

**@celom** · 1 upvotes

> Looks super cool and fun! Will try it

**@puppy** · 1 upvotes

> These are really neat! Thanks for sharing. I bet this took quite a while to put together.

**@the\_seth** · 1 upvotes

> These are the kinds of icon animations we need!

---

Tags: [#react](https://daily.dev/tags/react), [#web-animation](https://daily.dev/tags/web-animation)

[View this post on daily.dev](https://daily.dev/posts/morphicons-any-stroke-icon-morphs-into-any-other-qpdg4dbpn)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"DiscussionForumPosting","mainEntityOfPage":"https://daily.dev/posts/morphicons-any-stroke-icon-morphs-into-any-other-qpdg4dbpn","headline":"morphicons: any stroke icon morphs into any other","text":"morphicons is a React library for animating icon transitions using Procrustes-based optimal 2D similarity solving and polar-space interpolation. It requires no per-pair configuration — rotations emerge automatically (e.g., arrow-right to arrow-down yields 90°, plus to X yields 45°). The API is a single prop change on a MorphIcon component, with three modes: uncontrolled, controlled (for gestures/scroll), and imperative via ref. Features include real mid-flight interruption with velocity preservation, clean SSR with zero flash, drop-in Lucide compatibility, accessibility support, and prefers-reduced-motion handling. Works with Lucide, Tabler, Heroicons, Iconoir, and shadcn icons. MIT licensed, zero runtime deps, 7.65 KB gzipped.","url":"https://daily.dev/posts/morphicons-any-stroke-icon-morphs-into-any-other-qpdg4dbpn","datePublished":"2026-08-02T06:55:40.772Z","dateModified":"2026-08-02T18:17:29.409Z","author":{"@type":"Person","name":"Guillermo López","url":"https://daily.dev/guillermolg","image":"https://avatars.githubusercontent.com/u/85084558?v=4","description":"Full Stack developer","interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":730}},"image":"https://media.daily.dev/image/upload/s--30O0uVti--/f_auto/v1785598639/posts/SqKO7F9qj?_a=BAMAMicg0","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":149},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":12}],"comment":[{"@type":"Comment","text":"Incredibly cool.","datePublished":"2026-08-02T15:39:20.071Z","url":"https://daily.dev/posts/QpDg4dbpN#c-I6WTK3O8I","author":{"@type":"Person","name":"FG","url":"https://daily.dev/feforeboot","image":"https://media.daily.dev/image/upload/s--O0TOmw4y--/f_auto/v1715772965/public/noProfile"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":3}},{"@type":"Comment","text":"This looks very cool 😁. Think iam gonna use it some day but please also add Vue support.","datePublished":"2026-08-02T14:59:01.351Z","url":"https://daily.dev/posts/QpDg4dbpN#c-enaHknlzX","author":{"@type":"Person","name":"Daniel Peinhopf","url":"https://daily.dev/sevensolutions","image":"https://avatars.githubusercontent.com/u/84123899?v=4"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2}},{"@type":"Comment","text":"Looks super cool and fun! Will try it","datePublished":"2026-08-03T11:07:24.492Z","url":"https://daily.dev/posts/QpDg4dbpN#c-J7Lmi0vSh","author":{"@type":"Person","name":"Carlos Mimoso","url":"https://daily.dev/celom","image":"https://avatars.githubusercontent.com/u/15002036?v=4"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1}},{"@type":"Comment","text":"These are really neat! Thanks for sharing. I bet this took quite a while to put together.","datePublished":"2026-08-03T00:44:33.021Z","url":"https://daily.dev/posts/QpDg4dbpN#c-DG1GvIdBF","author":{"@type":"Person","name":"Sierra Layla Vithica","url":"https://daily.dev/puppy","image":"https://media.daily.dev/image/upload/s--10uW8345--/f_auto/v1781470592/avatars/avatar_fSoHwX6emdcRFMU5GE7Nb?_a=BAMAMiWQ0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1}},{"@type":"Comment","text":"These are the kinds of icon animations we need!","datePublished":"2026-08-04T15:31:29.580Z","url":"https://daily.dev/posts/QpDg4dbpN#c-1rWNxT1mr","author":{"@type":"Person","name":"Seth","url":"https://daily.dev/the_seth","image":"https://media.daily.dev/image/upload/s--T2HWW4NV--/f_auto/v1781641936/avatars/avatar_kVHvRNjcSZYByqpJjBnEN?_a=BAMAMiWQ0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1}}],"isPartOf":{"@type":"WebPage","url":"https://daily.dev/squads/webdev","name":"WebDev"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"WebDev","item":"https://daily.dev/squads/webdev"},{"@type":"ListItem","position":3,"name":"morphicons: any stroke icon morphs into any other"}]}
```

