# Morphing Modal

Multi-step modal that smoothly resizes to fit each page as content swaps in place. It grows out of the button that opened it, confirms with a check, then closes back into it.

> Composed · Pro · Overlays — React Native, Expo Go incompatible (dev build required).

## Install

```bash
npx @lumioui/cli add pro/morphing-modal
```

## Import

```tsx
import { MorphingModal } from "@/components/ui/morphing-modal/morphing-modal";
```

## Props

| Prop | Type | Notes |
| --- | --- | --- |
| `open` | `boolean` | — |
| `onOpenChange` | `(open: boolean) => void` | — |
| `title?` | `string` | Modal title (also the accessible name). Swaps in place when it changes. |
| `description?` | `string` | Optional line under the title. Swaps in place when it changes. |
| `showCloseButton?` | `boolean` | Show the close / back control. Default true. |
| `dismissible?` | `boolean` | Close on backdrop press and drag. Default true. |
| `swipeToDismiss?` | `boolean` | Drag the panel down to dismiss. Default true. |
| `placement?` | `"center" | "bottom"` | "center" floats mid-screen; "bottom" rests inset above the bottom edge. |
| `material?` | `"solid" | "glass"` | Surface material. "solid" (default) or "glass" — only over photos/video. |
| `step?` | `number` | Current step, 0-based. A change swaps the page in place; above 0 (with  `onBack`) the close glyph becomes a back arrow. |
| `stepCount?` | `number` | Number of steps — drives the step track and the "Step n of m" announcement. |
| `onBack?` | `() => void` | Go back one step (back arrow, Escape, Android back). |
| `action?` | `MorphingModalAction` | Primary button docked at the bottom of the panel, shared by every step. |
| `contentKey?` | `string | number` | Identity of the current page when it isn't `step`. A change swaps the page. |
| `maxWidth?` | `number` | Panel width cap; changing it springs the width. Default 400. |
| `originRef?` | `React.RefObject<View | null>` | Grow out of this view's rect and close back into it. |
| `closeInto?` | `React.RefObject<View | null>` | Close by shrinking into this view instead (e.g. the card the flow was about). |
| `onClosed?` | `() => void` | Fires once the panel has fully left. |
| `className?` | `string` | — |
| `children?` | `React.ReactNode` | — |

Source: https://lumioui.com/components/morphing-modal