Component
ResponsiveDialog
ResponsiveDialog automatically selects the interaction appropriate to the current media query while retaining one owner for open state.
Preview
Resize the browser to see the presentation change.
Installation
pnpm dlx shadcn@latest add https://pwaui.com/r/responsive-dialog.jsonUsage
import { ResponsiveDialog } from "@/components/ui/responsive-dialog"
export function EditProfile() { return ( <ResponsiveDialog> <ResponsiveDialog.Trigger>Edit profile</ResponsiveDialog.Trigger> <ResponsiveDialog.Content> <ResponsiveDialog.Header> <ResponsiveDialog.Title>Edit profile</ResponsiveDialog.Title> <ResponsiveDialog.Description>Update your details.</ResponsiveDialog.Description> </ResponsiveDialog.Header> </ResponsiveDialog.Content> </ResponsiveDialog> )}Anatomy
ResponsiveDialogTriggerContentHeaderTitleDescriptionCloseBehavior notes
- Default breakpoint is max-width: 47.999rem.
- The open state remains valid when the presentation changes.
- Lift local form state above Content when it must survive a breakpoint remount.
Platform limitations
- Crossing the breakpoint while open swaps the dialog and sheet implementations, which remounts the content subtree and resets uncontrolled state and focus. Lift any state you must preserve above
Content. - The mobile/desktop choice is resolved on the client, so server-rendered markup assumes the desktop dialog until hydration.
Accessibility
Both presentations use Base UI primitives. Only one dialog or drawer root is mounted at a time, avoiding duplicate focus traps.