import {
Box,
Dialog,
DialogActions,
DialogContent,
DialogContentProps,
DialogProps,
DialogTitle,
DialogTitleProps,
IconButton,
Stack,
SxProps,
Theme,
} from "@linagora/twake-mui";
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
import CloseIcon from "@mui/icons-material/Close";
import OpenInFullIcon from "@mui/icons-material/OpenInFull";
import React, { ReactNode } from "react";
/**
* ResponsiveDialog - A reusable dialog component that can switch between normal and expanded modes
*
* Features:
* - Normal mode: Dialog with customizable max-width (default 570px)
* - Expanded mode: Full height dialog (excluding app header) with centered content container
* - Fully customizable with sx props for Dialog, DialogTitle, and DialogContent
* - Preserves app header visibility in expanded mode
*
* @example
* ```tsx
* Save}
* contentSx={{ padding: 3 }}
* >
*
*
* ```
*/
interface ResponsiveDialogProps extends Omit<
DialogProps,
"maxWidth" | "title"
> {
/** Whether the dialog is open */
open: boolean;
/** Callback fired when the dialog should be closed */
onClose: () => void;
/** Dialog title - can be string or custom ReactNode */
title: string | ReactNode;
/** Dialog content - form fields, text, etc. */
children: ReactNode;
/** Optional actions rendered in DialogActions (buttons, etc.) */
actions?: ReactNode;
/** Toggle between normal and expanded (fullscreen) mode */
isExpanded?: boolean;
/** Callback when expand/collapse button is clicked (required if using isExpanded) */
onExpandToggle?: () => void;
/** Max width in normal mode (default: "570px") */
normalMaxWidth?: string;
/** Max width of content container in expanded mode (default: "990px") */
expandedContentMaxWidth?: string;
/** Height of app header to preserve visibility (default: "90px") */
headerHeight?: string;
/** Spacing between children in normal mode (default: 2 = 16px) */
normalSpacing?: number;
/** Spacing between children in expanded mode (default: 2 = 16px) */
expandedSpacing?: number;
/** Custom styles for DialogContent - merged with base styles */
contentSx?: SxProps;
/** Custom styles for DialogTitle */
titleSx?: SxProps;
/** Additional props for DialogContent (excluding sx) */
dialogContentProps?: Omit;
/** Additional props for DialogTitle (excluding sx) */
dialogTitleProps?: Omit;
/** Whether to display dividers between title/content/actions */
dividers?: boolean;
/** Whether to show header action icons (expand/close) in normal mode (default: true) */
showHeaderActions?: boolean;
/** Whether to add border-top to DialogActions */
actionsBorderTop?: boolean;
/** Justify content alignment for DialogActions */
actionsJustifyContent?:
| "flex-start"
| "center"
| "flex-end"
| "space-between";
}
function ResponsiveDialog({
open,
onClose,
title,
children,
actions,
isExpanded = false,
onExpandToggle,
normalMaxWidth = "570px",
expandedContentMaxWidth = "990px",
headerHeight = "70px",
normalSpacing = 2,
expandedSpacing = 2,
contentSx,
titleSx,
dialogContentProps,
dialogTitleProps,
dividers = false,
showHeaderActions = true,
actionsBorderTop = false,
actionsJustifyContent = "flex-end",
sx,
...otherDialogProps
}: ResponsiveDialogProps) {
const baseSx: SxProps = {
"& .MuiBackdrop-root": {
backgroundColor: "rgba(0, 0, 0, 0.1)",
opacity: isExpanded ? "0 !important" : undefined,
transition: isExpanded ? "none !important" : undefined,
pointerEvents: isExpanded ? "none" : undefined,
},
"& .MuiDialog-paper": {
maxWidth: isExpanded ? "100%" : normalMaxWidth,
width: "100%",
height: isExpanded ? `calc(100vh - ${headerHeight})` : undefined,
margin: isExpanded ? `${headerHeight} 0 0 0` : "32px",
boxShadow: isExpanded ? "none !important" : undefined,
transition: isExpanded ? "none !important" : undefined,
zIndex: isExpanded ? 1200 : 1300,
},
"& .MuiDialogActions-root .MuiBox-root": {
maxWidth: isExpanded ? expandedContentMaxWidth : undefined,
margin: isExpanded ? "0 auto" : undefined,
padding: "0",
width: isExpanded ? "100%" : undefined,
justifyContent: isExpanded ? "flex-end" : undefined,
},
};
const baseContentSx: SxProps = {
width: "100%",
};
const contentWrapperSx: SxProps = {
maxWidth: isExpanded ? expandedContentMaxWidth : "100%",
margin: isExpanded ? "0 auto" : "0",
width: "100%",
};
React.useEffect(() => {
if (isExpanded) {
document.body.classList.add("fullscreen-view");
} else {
document.body.classList.remove("fullscreen-view");
}
}, [isExpanded]);
const handleClose = (
event: {},
reason: "backdropClick" | "escapeKeyDown"
) => {
if (isExpanded && reason === "backdropClick") {
return;
}
onClose();
};
const currentSpacing = isExpanded ? expandedSpacing : normalSpacing;
return (
);
}
export default ResponsiveDialog;