Centralized dialogs manager with option to handle state of multi-step dialogs
npm install mui-x-dialogs
import { ThemeProvider } from '@mui/material';
import { DialogsProvider } from 'mui-x-dialogs';
function Demo() {
return (
<ThemeProvider>
<DialogsProvider>{/* Your app here */}</DialogsProvider>
</ThemeProvider>
);
}
Package includes special dialog that can be used for confirmations. Component includes confirm and cancel buttons and supports children to display additional information about action. Use confirm
function to open a confirm dialog:
import { Button, Typography } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
const openDialog = () => dialogs.confirm({
title: 'Please confirm your action',
children: (
<Typography>
This action is so important that you are required to confirm it with a dialog. Please click
one of these buttons to proceed.
</Typography>
),
labels: { confirm: 'Confirm', cancel: 'Cancel' },
onCancel: () => console.log('Cancel'),
onConfirm: () => console.log('Confirmed'),
});
return <Button onClick={openDialog}>Open confirm dialog</Button>;
}
confirm
function accepts one argument with following properties:
-
dialogId
– dialog id, defaults to random id, can be used to close dialog programmatically -
children
– additional dialog content displayed before actions -
onCancel
– called when cancel button is clicked -
onConfirm
– called when confirm button is clicked -
closeOnConfirm
– should dialog be closed when confirm button is clicked, defaults totrue
-
closeOnCancel
– should dialog be closed when cancel button is clicked, defaults totrue
-
cancelProps
– cancel button props -
confirmProps
– confirm button props -
actionsProps
– buttonsDialogActions
props -
labels
– close, cancel and confirm buttons labels, can be defined on DialogsProvider
Using this properties you can customize confirm dialog to match current context requirements:
import { Button, Typography } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
const openDeleteDialog = () =>
dialogs.confirm({
title: 'Delete your profile',
maxWidth: 'lg',
children: (
<Typography>
Are you sure you want to delete your profile? This action is destructive and you will have
to contact support to restore your data.
</Typography>
),
labels: { confirm: 'Delete account', cancel: "No don't delete it" },
confirmProps: { color: 'error' },
onCancel: () => console.log('Cancel'),
onConfirm: () => console.log('Confirmed'),
});
return <Button onClick={openDeleteDialog} color="red">Delete account</Button>;
}
To setup shared labels for confirm dialogs set labels
on DialogsProvider
:
import { DialogsProvider } from 'mui-x-dialogs';
function Demo() {
return (
<DialogsProvider labels={{ confirm: 'Submit', cancel: 'Cancel' }}>
{/* Your app here */}
</DialogsProvider>
);
}
You can define any amount of dialogs in DialogsProvider context:
import { Button, Typography } from '@mui/material';
import { ContextDialogProps, DialogsProvider } from 'mui-x-dialogs';
const TestDialog = ({
context,
id,
innerProps,
}: ContextDialogProps<{ dialogBody: string }>) => (
<>
<Typography>{innerProps.dialogBody}</Typography>
<Button fullWidth onClick={() => context.closeDialog(id)}>
Close dialog
</Button>
</>
);
function Demo() {
return (
<DialogsProvider
dialogs={{ demonstration: TestDialog /* ...other dialogs */ }}
>
{/* Your app here */}
</DialogsProvider>
);
}
And then open one of these dialogs with dialogs.context
function. dialogs.context
function accepts 2 arguments: dialog key (should match one defined on DialogsProvider) and dialog props:
import { Button } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
return (
<Button
onClick={() =>
dialogs.context({
dialog: 'demonstration',
title: 'Test dialog from context',
innerProps: {
dialogBody:
'This dialog was defined in DialogsProvider, you can open it anywhere in you app with useDialogs hook',
},
})
}
>
Open demonstration context dialog
</Button>
);
}
By default innerProps
and dialog
are not typesafe. You can add typesafety with a Typescript module declaration.
const TestDialog = ({
context,
id,
innerProps,
}: ContextDialogProps<{ dialogBody: string }>) => (
<>
<Typography>{innerProps.dialogBody}</Typography>
<Button fullWidth onClick={() => context.closeDialog(id)}>
Close dialog
</Button>
</>
);
const dialogs = {
demonstration: TestDialog,
/* ...other dialogs */
};
declare module 'mui-x-dialogs' {
export interface DialogsOverride {
dialogs: typeof dialogs;
}
}
function Demo() {
return (
<DialogsProvider dialogs={dialogs}>
{/* Your app here */}
</DialogsProvider>
);
}
Typesafe context dialogs will force you to use the correct types for openContextDialog
:
import { closeDialog, openContextDialog } from 'mui-x-dialogs';
openContextDialog({
dialog: 'demonstration',
title: 'Test dialog from context',
innerProps: {
dialogBody:
'This dialog was defined in DialogsProvider, you can open it anywhere in you app with useDialogs hook',
},
});
closeDialog('demonstration');
With dialogs.open function you can open a dialog with any content:
import { TextField, Button } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
return (
<Button
onClick={() => {
dialogs.open({
title: 'Subscribe to newsletter',
children: (
<>
<TextField label="Your email" placeholder="Your email" autoFocus />
<Button fullWidth onClick={() => dialogs.closeAll()} mt="md">
Submit
</Button>
</>
),
});
}}
>
Open content dialog
</Button>
);
}
open
function accepts one argument with following properties:
-
dialogId
– dialog id, defaults to random id, can be used to close dialog programmatically -
children
– additional dialog content displayed before actions -
closeProps
– close button props -
actionsProps
– buttonsDialogActions
props -
labels
– close buttons labels, can be defined on DialogsProvider -
withCloseButton
– without button, press escape or click on overlay to close
Using this properties you can customize confirm dialog to match current context requirements:
import { TextField, Button } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
return (
<Button
onClick={() => {
dialogs.open({
title: 'Alert!',
withCloseButton: true,
children: 'This is an important alert message. Please take note.';
labels: { close: 'Ok' }
}}
>
Open content dialog
</Button>
);
}
You can open multiple layers of dialogs. Every opened dialog is added as first element in dialogs queue. To close all opened dialogs call dialogs.closeAll()
function:
import { Button, Typography } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
return (
<Button
onClick={() =>
dialogs.confirm({
title: 'Please confirm your action',
closeOnConfirm: false,
labels: { confirm: 'Next dialog', cancel: 'Close dialog' },
children: (
<Typography>
This action is so important that you are required to confirm it with a dialog. Please
click one of these buttons to proceed.
</Typography>
),
onConfirm: () =>
dialogs.confirm({
title: 'This is dialog at second layer',
labels: { confirm: 'Close dialog', cancel: 'Back' },
closeOnConfirm: false,
children: (
<Typography>
When this dialog is closed dialogs state will revert to first dialog
</Typography>
),
onConfirm: dialogs.closeAll,
}),
})
}
>
Open multiple steps dialog
</Button>
);
}
You can pass props down to the Dialog
component by adding them to the argument of every dialogs.x
function. Example of setting maxWidth
, fullWidth
and scroll
props:
import { Button, Typography } from '@mui/material';
import { dialogs } from 'mui-x-dialogs';
function Demo() {
const openDialog = () => dialogs.confirm({
title: 'Please confirm your action',
maxWidth: 'sm',
fullWidth: true,
scroll: 'body',
children: (
<Typography>
This action is so important that you are required to confirm it with a dialog. Please click
one of these buttons to proceed.
</Typography>
),
labels: { confirm: 'Confirm', cancel: 'Cancel' },
onCancel: () => console.log('Cancel'),
onConfirm: () => console.log('Confirmed'),
});
return <Button onClick={openDialog}>Open confirm dialog</Button>;
}
Note that when using the Dialogs manager, dynamic content is not supported. Once dialog is opened, a snapshot is saved into internal state and cannot be updated.
If you intend to have dynamic content in dialogs, either:
- Use internal component state, or
- Use the dialog component instead of dialogs manager
We would like to thank the Mantine project for serving as a foundation and inspiration for building this package. Much of the code and ideas originated from this project.