# Dialog Layer A global dialog management system that allows you to open dialogs from anywhere in your application without mounting multiple instances. ## Features - ✅ Stack-based system - Dialogs can open other dialogs - ✅ Reactive config updates - Dialog config stays in sync with component state - ✅ Two usage patterns - Simple API and Composition Components - ✅ Smooth animations - Built-in open/close transitions - ✅ Flexible - Use simple props or build custom layouts - ✅ Uses design-system components - All content uses Dialog composition components from design-system ## File Structure ``` src/components/layers/Dialogs/ ├── hooks.ts # useDialogLayer, useDialogLayerItem hooks ├── types.ts # TypeScript type definitions ├── index.tsx # DialogLayerProvider and Dialog exports ├── stories.tsx # Storybook stories └── README.md # This file ``` ## Setup Wrap your application with the `DialogLayerProvider`: ```tsx import { DialogLayerProvider } from '@material-hu/layers/Dialogs'; function App() { return ( ); } ``` ## Usage **Props:** Use `dialogProps` for the MUI Dialog wrapper (e.g. `maxWidth`, `fullWidth`, `PaperProps`). Content config (title, textBody, or content) stays at top level. ### 1. Simple API Use the simple API for common dialog patterns. This uses the design-system Dialog component internally. ```tsx import { useDialogLayer } from '@material-hu/layers/Dialogs'; function MyComponent() { const { openDialog, closeDialog } = useDialogLayer(); const handleConfirm = () => { openDialog({ title: 'Confirm action', textBody: 'Are you sure you want to continue?', primaryButtonProps: { children: 'Continue', onClick: () => { doSomething(); closeDialog(); }, }, secondaryButtonProps: { children: 'Cancel', onClick: closeDialog, }, dialogProps: { maxWidth: 'sm', fullWidth: true, }, }); }; return ; } ``` #### Simple API Props | Prop | Type | Description | |------|------|-------------| | `title` | `string` | Dialog title | | `textBody` | `string` | Simple text content | | `body` | `ReactNode` | Custom body component | | `actionInfo` | `string` | Info text in footer | | `onClose` | `(reason?: DialogCloseReason) => void` | Close handler (handled by layer) | | `primaryButtonProps` | `ButtonProps` | Primary action button | | `secondaryButtonProps` | `ButtonProps` | Secondary action button | | `footerProps` | `{ hideBorder?: boolean }` | Footer styling | | `dialogProps` | `Omit` | Optional. Props for the MUI Dialog wrapper (`maxWidth`, `fullWidth`, `PaperProps`, etc.). | | `disableCloseOnBackdropClick` | `boolean` | If true, backdrop click does not close | | `disableCloseOnEscapeKeyDown` | `boolean` | If true, escape key does not close | ### 2. useDialogLayerItem Hook Use this hook when you need a dialog with **reactive config updates**. The dialog configuration automatically stays in sync with your component's state. ```tsx import { useDialogLayerItem } from '@material-hu/layers/Dialogs'; function MyComponent() { const [isLoading, setIsLoading] = useState(false); const { openDialog, closeDialog } = useDialogLayerItem('confirm-save', { title: 'Confirm Save', textBody: 'Are you sure you want to save these changes?', primaryButtonProps: { children: isLoading ? 'Saving...' : 'Save', loading: isLoading, onClick: async () => { setIsLoading(true); await saveChanges(); setIsLoading(false); closeDialog(); }, }, secondaryButtonProps: { children: 'Cancel', onClick: () => closeDialog(), }, }); return ; } ``` #### useDialogLayerItem API | Parameter | Type | Description | |-----------|------|-------------| | `id` | `string` | Unique identifier for the dialog | | `config` | `OpenDialogArgs` | Dialog configuration (same props as `openDialog`) | **Returns:** | Method | Type | Description | |--------|------|-------------| | `openDialog` | `(config?: OpenDialogArgs) => void` | Opens the dialog (optionally with different config) | | `closeDialog` | `(immediate?: boolean) => void` | Closes the dialog | | `updateDialogConfig` | `(setter: (current) => new) => void` | Manually update dialog config | #### When to use each hook | Use case | Hook | |----------|------| | Simple one-off dialogs | `useDialogLayer` | | Dialogs with reactive state (loading, form data) | `useDialogLayerItem` | | Programmatic config updates | `useDialogLayerItem` | ### 3. Composition Components API Use composition components for complete flexibility in layout and content. Pass **`content`** (your composed JSX) and optionally **`dialogProps`** for the MUI Dialog wrapper. ```tsx import { useDialogLayer, Dialog } from '@material-hu/layers/Dialogs'; function MyComponent() { const { openDialog, closeDialog } = useDialogLayer(); const handleCustomDialog = () => { openDialog({ content: ( <> ), dialogProps: { maxWidth: 'md', fullWidth: true, }, }); }; return ; } ``` #### Composition API props | Prop | Type | Description | |------|------|-------------| | `content` | `ReactNode` | **Required.** Your composed layout (e.g. `Dialog.Header` + `Dialog.Body` + `Dialog.Footer`). | | `onClose` | `(reason?: DialogCloseReason) => void` | Close handler (handled by layer). | | `dialogProps` | `Omit` | Optional. Props for the MUI Dialog wrapper. | | `disableCloseOnBackdropClick` | `boolean` | If true, backdrop click does not close | | `disableCloseOnEscapeKeyDown` | `boolean` | If true, escape key does not close | #### Available Composition Components ##### `Dialog.Header` Header section with title and close button. ```tsx ``` ##### `Dialog.Body` Content section with automatic scroll support. ```tsx ``` ##### `Dialog.Footer` Footer section for actions and optional info. ```tsx ``` ## Examples ### Simple confirmation ```tsx openDialog({ title: 'Confirm Action', textBody: 'Are you sure you want to proceed?', primaryButtonProps: { children: 'Yes, proceed', onClick: () => { doSomething(); closeDialog(); }, }, secondaryButtonProps: { children: 'Cancel', onClick: closeDialog, }, }); ``` ### Dialog with custom layout ```tsx openDialog({ content: ( <> ), }); ``` ### Minimal dialog (header only) ```tsx openDialog({ content: , }); ``` ## Behavior Notes - **Stack**: Dialogs can be stacked; opening a new one adds to the stack. Closing removes the topmost. - **Session Management**: Each dialog can have a unique ID when using `openDialog(args, id)` for targeted close/update. - **Immediate Close**: Pass `true` to `closeDialog(undefined, true)` to close without animation (useful before navigation). - **Auto Cleanup**: Dialog state is automatically cleaned up after close animations complete. ## TypeScript Support Full TypeScript support with exported types: ```tsx import type { OpenDialogArgs, SimpleDialogProps, CompositionDialogProps, DialogLayerContextValue, DialogLevel, DialogCloseReason, } from '@material-hu/layers/Dialogs/types'; ``` - **`OpenDialogArgs`** – Argument for `openDialog` / `useDialogLayerItem` config. Simple (design-system props) or Composition (`content`). Optional `dialogProps` for the MUI Dialog wrapper. - **`DialogCloseReason`** – `'backdropClick' | 'escapeKeyDown'`. ### Available Exports ```tsx // Main exports import { DialogLayerProvider, // Context provider useDialogLayer, // Basic dialog hook useDialogLayerItem, // Reactive dialog hook Dialog, // Composition components } from '@material-hu/layers/Dialogs'; // Composition components Dialog.Header Dialog.Body Dialog.Footer ```