MorphDialog
Root of a dialog that morphs open from its trigger via a shared-element
layout animation — the trigger and the dialog card share a layoutId, so
Motion tweens position, size, radius, and shadow between them.
Controlled when open is passed, otherwise uncontrolled. Provides context
to the trigger, content, title, and description parts.
A cut sample of Terrazzo Bianco ships to your studio in 3–5 days.
Usage
import { MorphDialog, MorphDialogContent, MorphDialogDescription, MorphDialogTitle, MorphDialogTrigger, useMorphDialog } from "@desk/ui/components/morph-dialog";Best practices
Reach for
MorphDialogonly when the modal should animate out of its trigger element (shared-layout); a plain centered modal is aDialog.Pass the trigger's
borderRadius/boxShadowviastyle(notclassName) onMorphDialogTriggerso Motion can correct their distortion during the morph.Render a
MorphDialogTitle(usevisuallyHiddenif needed) for the accessible name; mountReducedMotionProviderat the app root since it animates viam.*.
Props
MorphDialog
| Prop | Type | Default | Description |
|---|---|---|---|
| children | import("react").ReactNode | ||
| onOpenChange | (open: boolean) => void | Callback when open state changes | |
| open | boolean | Controlled open state. Omit to let the dialog manage its own open state. |
MorphDialogContent
| Prop | Type | Default | Description |
|---|---|---|---|
| children | import("react").ReactNode | ||
| className | string | ||
| data-testid | string | Test ID for E2E testing | |
| position | "center" | "bottom" | Position of the dialog. "center" (default) centers in viewport, "bottom" anchors near bottom for thumb reach |
MorphDialogDescription
| Prop | Type | Default | Description |
|---|---|---|---|
| children | import("react").ReactNode | ||
| className | string | ||
| visuallyHidden | boolean | Visually hide but keep accessible to screen readers |
MorphDialogTitle
| Prop | Type | Default | Description |
|---|---|---|---|
| children | import("react").ReactNode | ||
| className | string | ||
| visuallyHidden | boolean | Visually hide but keep accessible to screen readers |
MorphDialogTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
| children | import("react").ReactNode | ||
| className | string | ||
| style | import("react").CSSProperties | Style props for the layoutId element (the one that morphs). Motion can only auto-correct borderRadius and boxShadow distortion if they're set via style prop, not className. Pass matching values from your trigger children here. |
Also exports
- const
useMorphDialog