"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 (
{description}