A multi-view modal that opens from the button that launched it and returns there on close; the panel height springs between views and content crossfades through a blur.
modaldialogoverlaylayout animationshared layoutsettingsnavigation
Installation
$npx shadcn@latest add @geturui/morphing-modal
Usage
usage.tsx
1import { MorphingModal } from "@/components/ui/morphing-modal";
2
3export function SettingsButton() {
4 return (
5 <MorphingModal
6 trigger="Settings"
7 views={[
8 {
9 id: "home",
10 title: "Settings",
11 content: (nav) => (
12 <button onClick={() => nav.go("profile")}>Edit profile</button>
13 ),
14 },
15 { id: "profile", title: "Profile", content: <ProfileForm /> },
16 ]}
17 />
18 );
19}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
trigger* | ReactNode | — | Content of the trigger button. The button itself morphs into the panel. |
views* | { id: string; title: ReactNode; description?: ReactNode; content: ReactNode | (nav) => ReactNode }[] | — | Views the panel can show. `nav` exposes go(id), back(), close(), view and canGoBack. |
initialView | string | views[0].id | View shown each time the modal opens. |
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
onOpenChange | (open: boolean) => void | — | Called when the modal opens or closes. |
width | number | 420 | Panel width in px, clamped to the viewport. |
triggerClassName | string | — | Classes for the trigger button. |
className | string | — | Classes for the panel. |
Accessibility
- The panel is a role="dialog" with aria-modal, labelled by the current view's title and described by its description.
- Focus moves to the view heading on open and on every view change; Tab and Shift+Tab stay inside the panel.
- Escape or a click on the backdrop closes it, and focus returns to the trigger.
- Back and close are real buttons with labels. Under reduced motion the morph becomes a short fade and content no longer slides.
- useMorphingModal() lets nested components navigate without prop drilling.