# Icon Morph Button

> Menu into close, play into pause: the strokes travel.

Each stroke moves along its own path on a spring, so the change reads as one object changing its mind. Pairs: menu-close, play-pause, plus-minus, arrow-check.

- Family: Buttons
- Plan: Creative. Included with Creative.
- Requires: React, Tailwind CSS v4 and the motion package
- Page with a live preview: https://galactrex.com/ui/icon-morph-button/
- Licence: https://galactrex.com/ui/license/

## Install

```sh
npx @galactrex/ui login   # once, with an API key from https://galactrex.com/account/
npx @galactrex/ui add icon-morph-button
```

It installs to `components/galactrex/icon-morph-button.tsx`, with the shared motion helpers beside it. First time in a project: `npx @galactrex/ui init` (setup guide: https://galactrex.com/docs/ui-components-setup/).

## Usage

```tsx
import { IconMorphButton } from "@/components/galactrex/icon-morph-button";

<IconMorphButton pair="menu-close" labels={["Open menu", "Close menu"]} active={open} onChange={setOpen} aria-expanded={open} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `pair` | `"menu-close" \| "play-pause" \| "plus-minus" \| "arrow-check"` | — | Which two icons. |
| `labels` | `[string, string]` | — | Names for the two states. |
| `active / defaultActive` | `boolean` | — | Controlled or initial state. |
| `onChange` | `(active: boolean) => void` | — | On toggle. |
| `size` | `number` | `22` | Icon size in px. |

## Variants

- **Menu.** With aria-expanded from your menu state.
- **Player.** play-pause for media.

## Accessibility

- Its accessible name follows the state.

## Motion

- SVG path interpolation per stroke on a spring.
- Reduced motion: icons swap.
