# 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
```