"use client"; /** * The shell the chat dialogs sit in: a bottom drawer on mobile, a centred * modal on desktop. * * Extracted because "Add members" and "New group" are the same shape — title, * a fixed toolbar of inputs, a scrolling list of people, a confirm button — * and each would otherwise carry its own copy of the drawer/modal split. * * Follows the pattern already used by ReportDialog and ShareModal: the same * `useMediaQuery("(max-width: 767px)")` breakpoint, vaul's Drawer below it, * and a portalled modal above. */ import type { ReactNode } from "react"; import { useEffect } from "react"; import { createPortal } from "react-dom"; import { X } from "lucide-react"; import { useMediaQuery } from "@/components/selection-toolbar/shared"; import { Drawer, DrawerContent, DrawerDescription, DrawerHeader, DrawerTitle, } from "@/components/ui/drawer"; export function ResponsiveDialog({ title, description, onClose, toolbar, footer, children, }: { title: string; description: string; onClose: () => void; /** Fixed block under the title — search fields, selected chips. */ toolbar?: ReactNode; /** Pinned action row at the bottom. */ footer?: ReactNode; /** The scrolling region between toolbar and footer. */ children: ReactNode; }) { const isMobile = useMediaQuery("(max-width: 767px)"); // Desktop only: Escape to dismiss, and lock the page behind the modal. The // drawer does both itself, and doubling up on the scroll lock fights vaul's // own body handling on iOS. useEffect(() => { if (isMobile) return; const onKey = (e: KeyboardEvent) => e.key === "Escape" && onClose(); document.addEventListener("keydown", onKey); const prev = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = prev; }; }, [isMobile, onClose]); if (isMobile) { return ( !o && onClose()}> {title} {description} {toolbar &&
{toolbar}
} {/* Capped rather than flex-1: a drawer sizes to its content, so an unbounded list would grow the sheet past the screen. */}
{children}
{footer &&
{footer}
}
); } if (typeof document === "undefined") return null; return createPortal( <>

{title}

{description}

{toolbar &&
{toolbar}
}
{children}
{footer &&
{footer}
}
, document.body, ); }