Reference


Dialog
Dialogs notify users about tasks, conveying important information, prompting decisions, or requiring interaction with multiple tasks.
A Dialog is a type of modal window that appears over app content to present critical information or request a decision. Dialogs block all app functionality when visible and remain on screen until confirmed, dismissed, or a necessary action is completed.
Dialogs are intentionally disruptive and should be used judiciously.
Introduction
Dialogs are created using a set of interconnected components:
- Dialog: the main component that displays the modal.
- Dialog Title: a container for the dialog’s title.
- Dialog Actions: an optional wrapper for the dialog’s buttons.
- Dialog Content: an optional container for the dialog’s main content.
- Dialog Content Text: a wrapper for text within
<DialogContent />
. - Slide: an optional Transition that animates the dialog entering from the screen’s edge.
Selected: user02@gmail.com
import * as React from 'react'; import Button from '@mui/material/Button'; import Avatar from '@mui/material/Avatar'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemAvatar from '@mui/material/ListItemAvatar'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import DialogTitle from '@mui/material/DialogTitle'; import Dialog from '@mui/material/Dialog'; import PersonIcon from '@mui/icons-material/Person'; import AddIcon from '@mui/icons-material/Add'; import Typography from '@mui/material/Typography'; import { blue } from '@mui/material/colors'; const emails = ['username@gmail.com', 'user02@gmail.com']; export interface SimpleDialogProps { open: boolean; selectedValue: string; onClose: (value: string) => void; } function SimpleDialog(props: SimpleDialogProps) { const { onClose, selectedValue, open } = props; const handleClose = () => { onClose(selectedValue); }; const handleListItemClick = (value: string) => { onClose(value); }; return ( <Dialog onClose={handleClose} open={open}> <DialogTitle>Set backup account</DialogTitle> <List sx={{ pt: 0 }}> {emails.map((email) => ( <ListItem disablePadding key={email}> <ListItemButton onClick={() => handleListItemClick(email)}> <ListItemAvatar> <Avatar sx={{ bgcolor: blue[100], color: blue[600] }}> <PersonIcon /> </Avatar> </ListItemAvatar> <ListItemText primary={email} /> </ListItemButton> </ListItem> ))} <ListItem disablePadding> <ListItemButton autoFocus onClick={() => handleListItemClick('addAccount')} > <ListItemAvatar> <Avatar> <AddIcon /> </Avatar> </ListItemAvatar> <ListItemText primary="Add account" /> </ListItemButton> </ListItem> </List> </Dialog> ); } export default function SimpleDialogDemo() { const [open, setOpen] = React.useState(false); const [selectedValue, setSelectedValue] = React.useState(emails[1]); const handleClickOpen = () => { setOpen(true); }; const handleClose = (value: string) => { setOpen(false); setSelectedValue(value); }; return ( <div> <Typography variant="subtitle1" component="div"> Selected: {selectedValue} </Typography> <br /> <Button variant="outlined" onClick={handleClickOpen}> Open simple dialog </Button> <SimpleDialog selectedValue={selectedValue} open={open} onClose={handleClose} /> </div> ); }
Basics
import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle';
Alerts
Alerts are critical interruptions that require user acknowledgment to address a situation.
Most alerts do not require titles. They concisely present a decision by either:
- Posing a question (e.g., "Delete this conversation?")
- Providing a statement tied to the action buttons
Title bar alerts should be reserved for high-risk scenarios, such as potential connectivity loss. Users should understand the options based solely on the title and button text.
If a title is needed:
- Use a straightforward question or statement with a detailed explanation in the content area, such as "Erase USB storage?".
- Avoid vague or apologetic phrases, such as "Warning!" or "Are you sure?"
import * as React from 'react'; import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; export default function AlertDialog() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open alert dialog </Button> <Dialog open={open} onClose={handleClose} aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > <DialogTitle id="alert-dialog-title"> {"Use Google's location service?"} </DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-description"> Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running. </DialogContentText> </DialogContent> <DialogActions> <Button onClick={handleClose}>Disagree</Button> <Button onClick={handleClose} autoFocus> Agree </Button> </DialogActions> </Dialog> </React.Fragment> ); }
Transitions
You can replace the default transition with another, such as
Slide
, as shown in the next example.import * as React from 'react'; import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; import Slide from '@mui/material/Slide'; import { TransitionProps } from '@mui/material/transitions'; const Transition = React.forwardRef(function Transition( props: TransitionProps & { children: React.ReactElement<any, any>; }, ref: React.Ref<unknown>, ) { return <Slide direction="up" ref={ref} {...props} />; }); export default function AlertDialogSlide() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Slide in alert dialog </Button> <Dialog open={open} TransitionComponent={Transition} keepMounted onClose={handleClose} aria-describedby="alert-dialog-slide-description" > <DialogTitle>{"Use Google's location service?"}</DialogTitle> <DialogContent> <DialogContentText id="alert-dialog-slide-description"> Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running. </DialogContentText> </DialogContent> <DialogActions> <Button onClick={handleClose}>Disagree</Button> <Button onClick={handleClose}>Agree</Button> </DialogActions> </Dialog> </React.Fragment> ); }
Form dialogs
Form dialogs enable users to complete form fields within a dialog. For instance, a website might prompt potential subscribers to enter their email address and submit it by clicking "Submit".
import * as React from 'react'; import Button from '@mui/material/Button'; import TextField from '@mui/material/TextField'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; export default function FormDialog() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open form dialog </Button> <Dialog open={open} onClose={handleClose} slotProps={{ paper: { component: 'form', onSubmit: (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const formData = new FormData(event.currentTarget); const formJson = Object.fromEntries((formData as any).entries()); const email = formJson.email; console.log(email); handleClose(); }, }, }} > <DialogTitle>Subscribe</DialogTitle> <DialogContent> <DialogContentText> To subscribe to this website, please enter your email address here. We will send updates occasionally. </DialogContentText> <TextField autoFocus required margin="dense" id="name" name="email" label="Email Address" type="email" fullWidth variant="standard" /> </DialogContent> <DialogActions> <Button onClick={handleClose}>Cancel</Button> <Button type="submit">Subscribe</Button> </DialogActions> </Dialog> </React.Fragment> ); }
Customization
This example demonstrates how to customize the dialog component. Further details can be found in the overrides documentation page.
A close button has been added to the dialog to enhance usability.
import * as React from 'react'; import Button from '@mui/material/Button'; import { styled } from '@mui/material/styles'; import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import DialogActions from '@mui/material/DialogActions'; import IconButton from '@mui/material/IconButton'; import CloseIcon from '@mui/icons-material/Close'; import Typography from '@mui/material/Typography'; const BootstrapDialog = styled(Dialog)(({ theme }) => ({ '& .MuiDialogContent-root': { padding: theme.spacing(2), }, '& .MuiDialogActions-root': { padding: theme.spacing(1), }, })); export default function CustomizedDialogs() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open dialog </Button> <BootstrapDialog onClose={handleClose} aria-labelledby="customized-dialog-title" open={open} > <DialogTitle sx={{ m: 0, p: 2 }} id="customized-dialog-title"> Modal title </DialogTitle> <IconButton aria-label="close" onClick={handleClose} sx={(theme) => ({ position: 'absolute', right: 8, top: 8, color: theme.vars.palette.grey[500], })} > <CloseIcon /> </IconButton> <DialogContent dividers> <Typography gutterBottom> Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. </Typography> <Typography gutterBottom> Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. </Typography> <Typography gutterBottom> Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla. </Typography> </DialogContent> <DialogActions> <Button autoFocus onClick={handleClose}> Save changes </Button> </DialogActions> </BootstrapDialog> </React.Fragment> ); }
Full-screen dialogs
import * as React from 'react'; import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import ListItemText from '@mui/material/ListItemText'; import ListItemButton from '@mui/material/ListItemButton'; import List from '@mui/material/List'; import Divider from '@mui/material/Divider'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import CloseIcon from '@mui/icons-material/Close'; import Slide from '@mui/material/Slide'; import { TransitionProps } from '@mui/material/transitions'; const Transition = React.forwardRef(function Transition( props: TransitionProps & { children: React.ReactElement<unknown>; }, ref: React.Ref<unknown>, ) { return <Slide direction="up" ref={ref} {...props} />; }); export default function FullScreenDialog() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open full-screen dialog </Button> <Dialog fullScreen open={open} onClose={handleClose} TransitionComponent={Transition} > <AppBar sx={{ position: 'relative' }}> <Toolbar> <IconButton edge="start" color="inherit" onClick={handleClose} aria-label="close" > <CloseIcon /> </IconButton> <Typography sx={{ ml: 2, flex: 1 }} variant="h6" component="div"> Sound </Typography> <Button autoFocus color="inherit" onClick={handleClose}> save </Button> </Toolbar> </AppBar> <List> <ListItemButton> <ListItemText primary="Phone ringtone" secondary="Titania" /> </ListItemButton> <Divider /> <ListItemButton> <ListItemText primary="Default notification ringtone" secondary="Tethys" /> </ListItemButton> </List> </Dialog> </React.Fragment> ); }
Optional sizes
You can define a dialog’s maximum width using the
maxWidth
prop alongside the fullWidth
boolean. When fullWidth
is true, the dialog adjusts according to the maxWidth
value.import * as React from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Dialog, { DialogProps } from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; import FormControl from '@mui/material/FormControl'; import FormControlLabel from '@mui/material/FormControlLabel'; import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import Select, { SelectChangeEvent } from '@mui/material/Select'; import Switch from '@mui/material/Switch'; export default function MaxWidthDialog() { const [open, setOpen] = React.useState(false); const [fullWidth, setFullWidth] = React.useState(true); const [maxWidth, setMaxWidth] = React.useState<DialogProps['maxWidth']>('sm'); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; const handleMaxWidthChange = (event: SelectChangeEvent<typeof maxWidth>) => { setMaxWidth( // @ts-expect-error autofill of arbitrary value is not handled. event.target.value, ); }; const handleFullWidthChange = (event: React.ChangeEvent<HTMLInputElement>) => { setFullWidth(event.target.checked); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open max-width dialog </Button> <Dialog fullWidth={fullWidth} maxWidth={maxWidth} open={open} onClose={handleClose} > <DialogTitle>Optional sizes</DialogTitle> <DialogContent> <DialogContentText> You can set my maximum width and whether to adapt or not. </DialogContentText> <Box noValidate component="form" sx={{ display: 'flex', flexDirection: 'column', m: 'auto', width: 'fit-content', }} > <FormControl sx={{ mt: 2, minWidth: 120 }}> <InputLabel htmlFor="max-width">maxWidth</InputLabel> <Select autoFocus value={maxWidth} onChange={handleMaxWidthChange} label="maxWidth" inputProps={{ name: 'max-width', id: 'max-width', }} > <MenuItem value={false as any}>false</MenuItem> <MenuItem value="xs">xs</MenuItem> <MenuItem value="sm">sm</MenuItem> <MenuItem value="md">md</MenuItem> <MenuItem value="lg">lg</MenuItem> <MenuItem value="xl">xl</MenuItem> </Select> </FormControl> <FormControlLabel sx={{ mt: 1 }} control={ <Switch checked={fullWidth} onChange={handleFullWidthChange} /> } label="Full width" /> </Box> </DialogContent> <DialogActions> <Button onClick={handleClose}>Close</Button> </DialogActions> </Dialog> </React.Fragment> ); }
Responsive full-screen
A dialog can be made responsively full-screen by utilizing
useMediaQuery
.import useMediaQuery from '@mui/material/useMediaQuery'; function MyComponent() { const theme = useTheme(); const fullScreen = useMediaQuery(theme.breakpoints.down('md')); return <Dialog fullScreen={fullScreen} />; }
import * as React from 'react'; import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; import useMediaQuery from '@mui/material/useMediaQuery'; import { useTheme } from '@mui/material/styles'; export default function ResponsiveDialog() { const [open, setOpen] = React.useState(false); const theme = useTheme(); const fullScreen = useMediaQuery(theme.breakpoints.down('md')); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open responsive dialog </Button> <Dialog fullScreen={fullScreen} open={open} onClose={handleClose} aria-labelledby="responsive-dialog-title" > <DialogTitle id="responsive-dialog-title"> {"Use Google's location service?"} </DialogTitle> <DialogContent> <DialogContentText> Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running. </DialogContentText> </DialogContent> <DialogActions> <Button autoFocus onClick={handleClose}> Disagree </Button> <Button onClick={handleClose} autoFocus> Agree </Button> </DialogActions> </Dialog> </React.Fragment> ); }
Confirmation dialogs
Confirmation dialogs prompt users to explicitly verify their choice before committing to an action. For example, users may preview multiple ringtones but confirm their selection by clicking "OK".
Selecting "Cancel" in a confirmation dialog aborts the action, discards changes, and closes the dialog.
Interruptions
Phone ringtone
Dione
Default notification ringtone
Tethys
import * as React from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import List from '@mui/material/List'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import DialogActions from '@mui/material/DialogActions'; import Dialog from '@mui/material/Dialog'; import RadioGroup from '@mui/material/RadioGroup'; import Radio from '@mui/material/Radio'; import FormControlLabel from '@mui/material/FormControlLabel'; const options = [ 'None', 'Atria', 'Callisto', 'Dione', 'Ganymede', 'Hangouts Call', 'Luna', 'Oberon', 'Phobos', 'Pyxis', 'Sedna', 'Titania', 'Triton', 'Umbriel', ]; export interface ConfirmationDialogRawProps { id: string; keepMounted: boolean; value: string; open: boolean; onClose: (value?: string) => void; } function ConfirmationDialogRaw(props: ConfirmationDialogRawProps) { const { onClose, value: valueProp, open, ...other } = props; const [value, setValue] = React.useState(valueProp); const radioGroupRef = React.useRef<HTMLElement>(null); React.useEffect(() => { if (!open) { setValue(valueProp); } }, [valueProp, open]); const handleEntering = () => { if (radioGroupRef.current != null) { radioGroupRef.current.focus(); } }; const handleCancel = () => { onClose(); }; const handleOk = () => { onClose(value); }; const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { setValue((event.target as HTMLInputElement).value); }; return ( <Dialog sx={{ '& .MuiDialog-paper': { width: '80%', maxHeight: 435 } }} maxWidth="xs" TransitionProps={{ onEntering: handleEntering }} open={open} {...other} > <DialogTitle>Phone Ringtone</DialogTitle> <DialogContent dividers> <RadioGroup ref={radioGroupRef} aria-label="ringtone" name="ringtone" value={value} onChange={handleChange} > {options.map((option) => ( <FormControlLabel value={option} key={option} control={<Radio />} label={option} /> ))} </RadioGroup> </DialogContent> <DialogActions> <Button autoFocus onClick={handleCancel}> Cancel </Button> <Button onClick={handleOk}>Ok</Button> </DialogActions> </Dialog> ); } export default function ConfirmationDialog() { const [open, setOpen] = React.useState(false); const [value, setValue] = React.useState('Dione'); const handleClickListItem = () => { setOpen(true); }; const handleClose = (newValue?: string) => { setOpen(false); if (newValue) { setValue(newValue); } }; return ( <Box sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}> <List component="div" role="group"> <ListItemButton divider disabled> <ListItemText primary="Interruptions" /> </ListItemButton> <ListItemButton divider aria-haspopup="true" aria-controls="ringtone-menu" aria-label="phone ringtone" onClick={handleClickListItem} > <ListItemText primary="Phone ringtone" secondary={value} /> </ListItemButton> <ListItemButton divider disabled> <ListItemText primary="Default notification ringtone" secondary="Tethys" /> </ListItemButton> <ConfirmationDialogRaw id="ringtone-menu" keepMounted open={open} onClose={handleClose} value={value} /> </List> </Box> ); }
Non-modal dialog
Dialogs can be non-modal, allowing user interaction with the background content. For detailed guidance on modal vs. non-modal dialog usage, refer to the Nielsen Norman Group article.
The example below showcases a persistent cookie banner, a typical use case for non-modal dialogs.
import * as React from 'react'; import Stack from '@mui/material/Stack'; import TrapFocus from '@mui/material/Unstable_TrapFocus'; import CssBaseline from '@mui/material/CssBaseline'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Container from '@mui/material/Container'; import IconButton from '@mui/material/IconButton'; import MenuIcon from '@mui/icons-material/Menu'; import Paper from '@mui/material/Paper'; import Fade from '@mui/material/Fade'; import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; export default function CookiesBanner() { const [bannerOpen, setBannerOpen] = React.useState(true); const closeBanner = () => { setBannerOpen(false); }; return ( <React.Fragment> <CssBaseline /> <AppBar position="fixed" component="nav"> <Toolbar> <IconButton size="large" edge="start" color="inherit" aria-label="menu"> <MenuIcon /> </IconButton> </Toolbar> </AppBar> <Container component="main" sx={{ pt: 3 }}> <Toolbar /> <Typography sx={{ marginBottom: 2 }}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Rhoncus dolor purus non enim praesent elementum facilisis leo vel. Risus at ultrices mi tempus imperdiet. </Typography> <Typography sx={{ marginBottom: 2 }}> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Rhoncus dolor purus non enim praesent elementum facilisis leo vel. Risus at ultrices mi tempus imperdiet. </Typography> </Container> <TrapFocus open disableAutoFocus disableEnforceFocus> <Fade appear={false} in={bannerOpen}> <Paper role="dialog" aria-modal="false" aria-label="Cookie banner" square variant="outlined" tabIndex={-1} sx={{ position: 'fixed', bottom: 0, left: 0, right: 0, m: 0, p: 2, borderWidth: 0, borderTopWidth: 1, }} > <Stack direction={{ xs: 'column', sm: 'row' }} sx={{ justifyContent: 'space-between', gap: 2 }} > <Box sx={{ flexShrink: 1, alignSelf: { xs: 'flex-start', sm: 'center' } }} > <Typography sx={{ fontWeight: 'bold' }}> This website uses cookies </Typography> <Typography variant="body2"> example.com relies on cookies to improve your experience. </Typography> </Box> <Stack direction={{ xs: 'row-reverse', sm: 'row', }} sx={{ gap: 2, flexShrink: 0, alignSelf: { xs: 'flex-end', sm: 'center' }, }} > <Button size="small" onClick={closeBanner} variant="contained"> Allow all </Button> <Button size="small" onClick={closeBanner}> Reject all </Button> </Stack> </Stack> </Paper> </Fade> </TrapFocus> </React.Fragment> ); }
Draggable dialog
A draggable dialog can be created using react-draggable. Pass the imported
Draggable
component as the PaperComponent
of the Dialog
component to make the entire dialog draggable.import * as React from 'react'; import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; import Paper, { PaperProps } from '@mui/material/Paper'; import Draggable from 'react-draggable'; function PaperComponent(props: PaperProps) { const nodeRef = React.useRef<HTMLDivElement>(null); return ( <Draggable nodeRef={nodeRef as React.RefObject<HTMLDivElement>} handle="#draggable-dialog-title" cancel={'[class*="MuiDialogContent-root"]'} > <Paper {...props} ref={nodeRef} /> </Draggable> ); } export default function DraggableDialog() { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { setOpen(true); }; const handleClose = () => { setOpen(false); }; return ( <React.Fragment> <Button variant="outlined" onClick={handleClickOpen}> Open draggable dialog </Button> <Dialog open={open} onClose={handleClose} PaperComponent={PaperComponent} aria-labelledby="draggable-dialog-title" > <DialogTitle style={{ cursor: 'move' }} id="draggable-dialog-title"> Subscribe </DialogTitle> <DialogContent> <DialogContentText> To subscribe to this website, please enter your email address here. We will send updates occasionally. </DialogContentText> </DialogContent> <DialogActions> <Button autoFocus onClick={handleClose}> Cancel </Button> <Button onClick={handleClose}>Subscribe</Button> </DialogActions> </Dialog> </React.Fragment> ); }
Scrolling long content
When dialogs exceed the viewport or device height, they become scrollable.
scroll=paper
: the dialog’s content scrolls within the paper element.scroll=body
: the dialog’s content scrolls within the body element.
Explore the example below to understand this behavior:
import * as React from 'react'; import Button from '@mui/material/Button'; import Dialog, { DialogProps } from '@mui/material/Dialog'; import DialogActions from '@mui/material/DialogActions'; import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogTitle from '@mui/material/DialogTitle'; export default function ScrollDialog() { const [open, setOpen] = React.useState(false); const [scroll, setScroll] = React.useState<DialogProps['scroll']>('paper'); const handleClickOpen = (scrollType: DialogProps['scroll']) => () => { setOpen(true); setScroll(scrollType); }; const handleClose = () => { setOpen(false); }; const descriptionElementRef = React.useRef<HTMLElement>(null); React.useEffect(() => { if (open) { const { current: descriptionElement } = descriptionElementRef; if (descriptionElement !== null) { descriptionElement.focus(); } } }, [open]); return ( <React.Fragment> <Button onClick={handleClickOpen('paper')}>scroll=paper</Button> <Button onClick={handleClickOpen('body')}>scroll=body</Button> <Dialog open={open} onClose={handleClose} scroll={scroll} aria-labelledby="scroll-dialog-title" aria-describedby="scroll-dialog-description" > <DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle> <DialogContent dividers={scroll === 'paper'}> <DialogContentText id="scroll-dialog-description" ref={descriptionElementRef} tabIndex={-1} > {[...new Array(50)] .map( () => `Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`, ) .join('\n')} </DialogContentText> </DialogContent> <DialogActions> <Button onClick={handleClose}>Cancel</Button> <Button onClick={handleClose}>Subscribe</Button> </DialogActions> </Dialog> </React.Fragment> ); }
Performance
Refer to the Modal performance section for guidance.
Limitations
Consult the Modal limitations section for details.
Supplementary projects
For advanced scenarios, you may benefit from the following:
material-ui-confirm
The
material-ui-confirm
package offers dialogs for confirming user actions, reducing the need for boilerplate code.Accessibility
See the Modal accessibility section for accessibility guidance.