# StatusMorph

> A 1em SVG status icon that morphs between idle, loading, success, and error, closing its spinning ring into a drawn check or cross with a portalled live region announcing each state.

- Package: `fancy-ui-react` (React 18/19 + Tailwind CSS v4)
- Category: Feedback
- Tags: status, icon, loading, success, error, morph, micro-interaction
- Types: `StatusMorphProps`, `StatusMorphState`
- Docs: https://fancy-ui.rama.app/docs/components/status-morph
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/react/src/components/status-morph

## Import

```tsx
import { StatusMorph } from 'fancy-ui-react';
```

Setup (once per project): `npm install fancy-ui-react`, then put these lines in your main CSS file (the stylesheet import goes right after `@import "tailwindcss";`):

```css
@import "tailwindcss";
@import "fancy-ui-react/tailwind.css";
```

and import the component styles once in the app entry: `import "fancy-ui-react/styles.css";`. Full guide: https://fancy-ui.rama.app/llms.txt

The names below are the ones to write in React; when one differs from the Svelte name, the Svelte name follows in parentheses. `class` becomes `className`, a callback takes the name the React port declares (`onclick` becomes `onClick`), snippets become `ReactNode` props (render functions when they take arguments) and the default snippet is `children`. Divergences: https://github.com/RamaHerbin/fancy-ui/tree/main/react#divergences-from-the-svelte-api

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `state` | `"idle" \| "loading" \| "success" \| "error"` | `"idle"` | Current state, two-way bound. The component only ever writes it back to "idle" itself, when resetAfter fires — every other write is the caller's, and is always honoured |
| `resetAfter` | `number` | `1800` | Milliseconds until an automatic reset to "idle" after "success" or "error". 0 disables the timer entirely (manual reset only) |
| `labels` | `{ loading?: string; success?: string; error?: string }` | `{ loading: "Loading", success: "Done", error: "Failed" }` | Live-region text per state; unset keys fall back to the defaults |
| `tone` | `"current" \| "semantic"` | `"current"` | "current" paints every glyph in currentColor; "semantic" reads the shared --ft-status-running/-done/-error vocabulary instead |
| `haptic` | `boolean` | `false` | Best-effort tactile feedback (the success/error haptic patterns) on entering those states; silently a no-op wherever the Vibration API is unsupported or refused |
| `className` (Svelte `class`) | `string` | — | Additional CSS classes |
| `ref` | `HTMLSpanElement \| null` | `null` | Bindable reference to the root element |

## Node props

| Prop | Description |
| --- | --- |
| `idle` | Custom idle content, rendered in the same calc(1em + 1px) footprint instead of the default transparent scaffold, so swapping to it never shifts layout |

## Example

No React example is published for this component yet: start from the import above and the props table. The full examples are Svelte-only, on https://fancy-ui.rama.app/docs/components/status-morph.md.
