# Icon morph

> Kinetic SVG icon transition primitive and button with scale, rotate, and 3D horizon flip animations.

A micro-interaction primitive designed for icon state changes (Play/Pause, Menu/Close, Eye/EyeOff, Sun/Moon, Copy/Check). Instead of sudden swaps, icons morph continuously with spring settling, soft blurs, and rotational or 3D flips using 0 kB external animation dependencies.

## Install

```bash
npx shadcn@latest add https://hairlineui.com/r/icon-morph.json
```

Needs React 19, Tailwind CSS v4 and shadcn/ui theme variables (any style, light and dark). Icons from lucide-react.

- npm: none
- Hairline UI components it needs (the CLI installs them too): `ui-interaction-motion`
- Docs and live preview: https://hairlineui.com/ui/icon-morph
- Registry item (source): https://hairlineui.com/r/icon-morph.json

## Usage

```tsx
import { IconMorph, IconMorphButton } from "@/components/ui/icon-morph";
import { Play, Pause } from "lucide-react";

// As a standalone kinetic icon
<IconMorph from={<Play size={16} />} to={<Pause size={16} />} active={isPlaying} />

// As an interactive button
<IconMorphButton
  label="Toggle playback"
  active={isPlaying}
  onActiveChange={setIsPlaying}
  from={<Play size={15} />}
  to={<Pause size={15} />}
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `from` | `React.ReactNode` | – | First icon shown when inactive. |
| `to` | `React.ReactNode` | – | Second icon shown when active. |
| `active` | `boolean` | `false` | Active toggle state. |
| `mode` | `"scale" \| "rotate" \| "flip"` | `"scale"` | Kinetic transition mode. |
| `size` | `number` | `16` | Icon bounding dimension in pixels. |
| `variant` | `"outline" \| "ghost" \| "solid"` | `"outline"` | Button style (IconMorphButton only). |

## States

- **inactive**: Displays the "from" icon with full opacity.
- **active**: Smoothly transitions into the "to" icon using the chosen morph mode.

## What it handles

Standard icon swaps feel instant and disconnected, while Framer Motion icon morphs add heavy bundle weight. IconMorph provides native CSS/WAAPI kinetic transitions with zero bundle cost.

- **Three morph modes**: Supports scale with soft depth blur, planar rotate (0° → 90°), and 3D horizon flip (rotateY).
- **Standalone & button variants**: Use as a standalone kinetic icon primitive (IconMorph) or as an interactive button (IconMorphButton).
- **Concentric hairline pill**: Button variant includes outline, ghost, and solid styles with active scale damping.
- **Harmonic spring curve**: Transitions use cubic-bezier(0.22, 1.18, 0.36, 1) for a subtle 3% organic breath.

## Replaces

abrupt SVG swaps, heavy framer-motion icon wrappers, plain boolean ternary icons

## Where it fits

- **Media players & audio controls**: Play/Pause and Mute/Unmute state swaps with harmonic spring settle.
- **Navigation headers**: Mobile hamburger menu morphing into an X close button.
- **Theme & mode switchers**: Sun/Moon toggling with 3D horizon flip.
- **Password fields**: Eye to EyeOff toggle with soft depth blur.

## Notes

- Pure CSS transitions with will-change: transform ensure 60fps performance on all devices.
- Perspective is applied automatically for 3D flip mode.

License: MIT (https://hairlineui.com/license#components)
