> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/raphaelsalaja/userinterface-wiki/llms.txt
> Use this file to discover all available pages before exploring further.

# Morphing Icons

> Icons that transform through actual shape transformation, not crossfades. Every icon uses exactly three SVG lines.

# Morphing Icons

Icons that transform through actual shape transformation, not crossfades. Inspired by [Benji's experiments with Claude](https://benji.org/morphing-icons-with-claude).

## Core Concept

Every icon uses exactly **three SVG lines**. Icons that need fewer lines collapse the extras to invisible points. This means any icon can morph into any other since they share the same underlying structure.

## Three-Line Structure

All icons are defined with three lines, each with coordinates and optional opacity:

```tsx theme={null}
interface IconLine {
  x1: number;
  y1: number;
  x2: number;
  y2: number;
  opacity?: number;
}

interface IconDefinition {
  lines: [IconLine, IconLine, IconLine];
  rotation?: number;
  group?: string;
}
```

## Collapsed Lines

When an icon needs fewer than three lines, unused lines collapse to a single point at the center with zero opacity:

```tsx theme={null}
const CENTER = 7;

const collapsed: IconLine = {
  x1: CENTER,
  y1: CENTER,
  x2: CENTER,
  y2: CENTER,
  opacity: 0,
};
```

## Example Icons

### Menu Icon (3 lines)

```tsx theme={null}
menu: {
  lines: [
    { x1: 2, y1: 3.5, x2: 12, y2: 3.5 },
    { x1: 2, y1: 7, x2: 12, y2: 7 },
    { x1: 2, y1: 10.5, x2: 12, y2: 10.5 },
  ],
}
```

### Minus Icon (1 line + 2 collapsed)

```tsx theme={null}
minus: {
  lines: [
    { x1: 2, y1: 7, x2: 12, y2: 7 },
    collapsed,
    collapsed
  ],
}
```

### Check Icon (2 lines + 1 collapsed)

```tsx theme={null}
check: {
  lines: [
    { x1: 2, y1: 7.5, x2: 5.5, y2: 11 },
    { x1: 5.5, y1: 11, x2: 12, y2: 3 },
    collapsed,
  ],
}
```

## Rotation Groups

Icons with shared base shapes can rotate between variants instead of morphing lines. This is controlled by the `group` property:

```tsx theme={null}
// Plus and cross share the same lines but rotate
const plusLines: [IconLine, IconLine, IconLine] = [
  { x1: 7, y1: 2, x2: 7, y2: 12 },
  { x1: 2, y1: 7, x2: 12, y2: 7 },
  collapsed,
];

plus: { lines: plusLines, rotation: 0, group: "plus-cross" },
cross: { lines: plusLines, rotation: 45, group: "plus-cross" },
```

When transitioning between icons in the same group, the component rotates the existing lines rather than morphing them:

```tsx theme={null}
const shouldRotate = useMemo(() => {
  const prev = prevDefinitionRef.current;
  return prev.group && definition.group && prev.group === definition.group;
}, [definition]);
```

## Animation Implementation

The morphing effect uses motion's spring physics to animate line coordinates:

```tsx theme={null}
function AnimatedLine({ line, transition }: AnimatedLineProps) {
  return (
    <motion.line
      animate={{
        x1: line.x1,
        y1: line.y1,
        x2: line.x2,
        y2: line.y2,
        opacity: line.opacity ?? 1,
      }}
      transition={transition}
      strokeLinecap="round"
    />
  );
}
```

Default transition uses a custom easing curve for smooth, natural movement:

```tsx theme={null}
const defaultTransition: Transition = {
  ease: [0.19, 1, 0.22, 1],
  duration: 0.4,
};
```

## Accessibility

The component respects user motion preferences:

```tsx theme={null}
const reducedMotion = useReducedMotion() ?? false;
const activeTransition = reducedMotion ? { duration: 0 } : transition;
```

## Usage Example

```tsx theme={null}
import { MorphingIcon } from "@/components/morphing-icon";

function IconButton() {
  const [icon, setIcon] = useState("menu");

  return (
    <button onClick={() => setIcon(icon === "menu" ? "cross" : "menu")}>
      <MorphingIcon icon={icon} size={24} strokeWidth={1.5} />
    </button>
  );
}
```

## Available Icons

The system supports 27 icons:

* **Navigation**: menu, cross, chevron-right, chevron-down, chevron-left, chevron-up, arrow-right, arrow-down, arrow-left, arrow-up
* **Actions**: plus, minus, check, play, pause, download, upload, external
* **Symbols**: equals, asterisk, more, grip, slash, corner

## Reference

Inspired by [Benji's experiments with Claude](https://benji.org/morphing-icons-with-claude), demonstrating how AI-assisted design can explore systematic constraints that lead to elegant solutions.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.