Responsive Dialog

A dialog component that adapts to screen size - side dialog on desktop, drawer on mobile.

Installation

npx shadcn@latest add https://shuip.xyz/r/responsive-dialog.json

Preview

Basic Responsive Dialog

Different Positions (Desktop only)

Different Sizes (Desktop only)

Custom Breakpoints

Form Example

About

ResponsiveDialog is a smart dialog component that automatically adapts to the user's screen size:

  • Desktop (≥1024px): Renders as a SideDialog with flexible positioning
  • Mobile (<1024px): Renders as a Drawer for better mobile UX

Unlike traditional dialogs that force the same experience across all devices, ResponsiveDialog provides the optimal interface for each screen size while maintaining a consistent API.

Built-in features

  • Automatic responsive behavior: Switches between side dialog and drawer based on screen size
  • 6 positions (desktop): Choose from top-left, top-right, bottom-left, bottom-right, left, right
  • Flexible sizes (desktop): Predefined sizes (xs, sm, md, lg, xl, 2xl)
  • Mobile-optimized: Uses native drawer with swipe gestures on mobile
  • Lightweight: Combines existing components without additional overhead
  • Accessible: Inherits accessibility features from both SideDialog and Drawer

Installation

Usage

Basic responsive dialog

<ResponsiveDialog>
<ResponsiveDialogTrigger asChild>
<Button>Open Dialog</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Settings</ResponsiveDialogTitle>
<ResponsiveDialogDescription>
Manage your preferences and account settings.
</ResponsiveDialogDescription>
</ResponsiveDialogHeader>
<ResponsiveDialogFooter>
<ResponsiveDialogClose asChild>
<Button variant="outline">Cancel</Button>
</ResponsiveDialogClose>
<Button>Save</Button>
</ResponsiveDialogFooter>
</ResponsiveDialogContent>
</ResponsiveDialog>

Different positions (desktop only)

Desktop positions are ignored on mobile where the drawer behavior takes precedence:

// Notification from bottom-right
<ResponsiveDialog position="bottom-right">
<ResponsiveDialogTrigger asChild>
<Button>Show Notification</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Success!</ResponsiveDialogTitle>
<ResponsiveDialogDescription>Your changes have been saved.</ResponsiveDialogDescription>
</ResponsiveDialogHeader>
</ResponsiveDialogContent>
</ResponsiveDialog>
// User menu from top-right
<ResponsiveDialog position="top-right" size="sm">
<ResponsiveDialogTrigger asChild>
<Button variant="ghost" size="icon">
<User className="size-4" />
</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Account</ResponsiveDialogTitle>
</ResponsiveDialogHeader>
<div className="space-y-2">
<Button variant="ghost" className="w-full justify-start">
Profile Settings
</Button>
<Button variant="ghost" className="w-full justify-start">
Sign out
</Button>
</div>
</ResponsiveDialogContent>
</ResponsiveDialog>

Custom breakpoints

Control when the dialog switches between desktop and mobile modes:

// Use predefined breakpoints
<ResponsiveDialog breakpoint="sm"> {/* Switches at 640px */}
<ResponsiveDialogTrigger asChild>
<Button>Small Breakpoint</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Mobile at 640px</ResponsiveDialogTitle>
<ResponsiveDialogDescription>
This dialog becomes a drawer on screens smaller than 640px.
</ResponsiveDialogDescription>
</ResponsiveDialogHeader>
</ResponsiveDialogContent>
</ResponsiveDialog>
// Use custom pixel values
<ResponsiveDialog breakpoint={900}>
<ResponsiveDialogTrigger asChild>
<Button>Custom Breakpoint</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Custom at 900px</ResponsiveDialogTitle>
<ResponsiveDialogDescription>
Switches to mobile mode at exactly 900px and below.
</ResponsiveDialogDescription>
</ResponsiveDialogHeader>
</ResponsiveDialogContent>
</ResponsiveDialog>

Different sizes (desktop only)

Size props affect the desktop side dialog appearance:

// Small dialog for quick actions
<ResponsiveDialog size="xs">
<ResponsiveDialogTrigger asChild>
<Button variant="outline">Quick Action</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Confirm</ResponsiveDialogTitle>
<ResponsiveDialogDescription>Are you sure?</ResponsiveDialogDescription>
</ResponsiveDialogHeader>
</ResponsiveDialogContent>
</ResponsiveDialog>
// Large dialog for complex content
<ResponsiveDialog position="left" size="lg">
<ResponsiveDialogTrigger asChild>
<Button variant="outline">Navigation Menu</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Navigation</ResponsiveDialogTitle>
</ResponsiveDialogHeader>
<nav className="space-y-2">
<Link href="/dashboard">Dashboard</Link>
<Link href="/projects">Projects</Link>
<Link href="/settings">Settings</Link>
</nav>
</ResponsiveDialogContent>
</ResponsiveDialog>

Common use cases

Mobile-first navigation

<ResponsiveDialog position="left" size="lg">
<ResponsiveDialogTrigger asChild>
<Button variant="outline" size="icon">
<Menu className="size-4" />
</Button>
</ResponsiveDialogTrigger>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>Menu</ResponsiveDialogTitle>
</ResponsiveDialogHeader>
<nav className="space-y-3">
<Link href="/home" className="block p-2 hover:bg-muted rounded">
Home
</Link>
<Link href="/about" className="block p-2 hover:bg-muted rounded">
About
</Link>
<Link href="/contact" className="block p-2 hover:bg-muted rounded">
Contact
</Link>
</nav>
</ResponsiveDialogContent>
</ResponsiveDialog>

Examples

Default

Basic Responsive Dialog

Different Positions (Desktop only)

Different Sizes (Desktop only)

Custom Breakpoints

Form Example

Props

NameTypeDescription
booleanWhether the dialog is open. Use with onOpenChange for controlled component.
(open: boolean) => voidCallback fired when the dialog open state changes.
'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left' | 'right'Position of the dialog on desktop. Default is "bottom-right". Ignored on mobile.
'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'Size of the dialog on desktop. Default is "sm". Ignored on mobile.
'sm' | 'md' | 'lg' | 'xl' | numberBreakpoint at which the dialog switches to mobile mode. Default is "md" (768px). Can be a predefined breakpoint or custom pixel value.