Reputation: 1244
I Want to add the close icon in the header section at the top right corner.
I am using the Material UI Dialog. Everything is working fine, but I want the close button on top section, as shown in the image:
Upvotes: 46
Views: 109679
Reputation: 1275
Using the new Grid2 component from MUI v6 (released on August 27, 2024):
import { Dialog, DialogTitle, Grid2 as Grid, IconButton } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
const MyDialog = ({ onClose }) => (
<Dialog>
<DialogTitle>
<Grid container alignItems="center">
<Grid size="grow">Dialog Title</Grid>
<Grid>
<IconButton aria-label="Close" onClick={onClose}>
<CloseIcon />
</IconButton>
</Grid>
</Grid>
</DialogTitle>
</Dialog>
);
Upvotes: 0
Reputation: 63
For those using MUI 5, my solutions are shown below.
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, IconButton } from '@mui/material'
import CloseIcon from "@mui/icons-material/Close";
const [open, setOpen] = useState(false);
<Dialog open={open} onClose={() => setOpen(false)}>
<DialogTitle sx={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
{your title}
<IconButton onClick={() => setOpen(false)}><Close /></IconButton>
</DialogTitle>
<DialogContent>
<DialogContentText>{your content texts}</DialogContentText>
</DialogContent>
<DialogActions>
<Button>{your button text}</Button>
</DialogActions>
</Dialog>
Upvotes: 0
Reputation: 550
I don't think inserting the IconButton
inside the DialogTitle
is right, because it will render to a button
inside an h2
tag(!).
I found a very easy solution:
<Dialog
dir={dir}
open={shouldOpen}
onClose={reset}
>
<IconButton sx={{ position: "absolute" }}> {/* <--------- */}
<CloseIcon />
</IconButton>
<DialogTitle>
<Typography>
{i18n.title}
</Typography>
</DialogTitle>
</Dialog>
Just insert it directly under the Dialog
and add a position: "absolute"
css rule
Result: (Attention the location of the X)
Upvotes: 0
Reputation: 33
This is what we made, extending the default close reasons :
import { FC, useEffect, useState } from 'react'
import MUIDialog, { DialogProps as MUIDialogProps } from '@mui/material/Dialog'
import styled from 'styled-components'
import { DialogTitle } from '@mui/material'
export type DialogProps = MUIDialogProps & {
onClose?: (event: {}, reason: 'backdropClick' | 'escapeKeyDown' | 'closeIcon') => void
}
const StyledMaterialDialog = styled(MUIDialog)`
&.MuiDialog-root {
}
`
const Dialog: FC<DialogProps> = ({ children, ...props }) => {
const initialValue = !!props.open
const [open, setOpen] = useState(initialValue)
const forceClose = () => {
setOpen(false)
props.onClose && props.onClose({}, 'closeIcon')
}
useEffect(() => {
setOpen(!!props.open)
}, [props.open])
return (
<StyledMaterialDialog {...{ ...props, open }}>
<DialogTitle className="flex flex-row">
<div className="flex-1">Title</div>
<div onClick={forceClose}>X</div>
</DialogTitle>
{children}
</StyledMaterialDialog>
)
}
export default Dialog
Upvotes: 0
Reputation: 3109
My solution:
<IconButton
open={open}
onClose={handleClose}
aria-label="Close"
onClick={handleClose}
sx={{
position: 'absolute',
right: 6,
top: 6,
color: 'black',
fontSize: 34
}}
>
<CloseIcon />
</IconButton>
Upvotes: 0
Reputation: 6238
This is the way I am doing it with MUI 5, using the Grid component.
import React from "react";
import Dialog from "@mui/material/Dialog";
import { DialogContent, DialogTitle, Grid, IconButton } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close";
<Dialog
fullWidth
maxWidth="sm"
onClose={handleClose}
PaperProps={{
sx: {
position: "fixed",
top: 10,
left: 0,
right: 0,
m: "0 auto",
},
}}
>
<DialogTitle>
<Grid container>
<Grid item>Title</Grid>
<Grid ml="auto" item>
<IconButton aria-label="close" onClick={handleClose}>
<CloseIcon />
</IconButton>
</Grid>
</Grid>
</DialogTitle>
<DialogContent>
<p>Content</p>
</DialogContent>
</Dialog>
The dialog is positioned on the top, centered horizontally, and a small width.
Upvotes: 0
Reputation: 48899
MUI 5 solution with no tricks or absolute positioning (only flex):
<DialogTitle sx={{ display: 'flex', alignItems: 'center' }}>
Dialog Title
<IconButton sx={{ ml: 'auto' }}>
<CloseIcon />
</IconButton>
</DialogTitle>
Upvotes: 5
Reputation: 729
From the MUI Docs: Customized Dialog
Use the sx
property.
// import mui components as needed
...
return (
<Dialog
className='modal-dialog'
open={isModalOpen}
onClose={onClose}
>
<DialogTitle sx={{m: 0, p: 2}}>
<IconButton
aria-label="close"
onClick={onClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
color: (theme) => theme.palette.grey[500],
}}
>
<CloseIcon/>
</IconButton>
</DialogTitle>
<DialogContent>
<DialogContentText>
Your dialog content here
</DialogContentText>
</DialogContent>
</Dialog>
);
Upvotes: 3
Reputation: 554
Here is the most minimalist code I know that does that with only inline css.
import React, { useState } from "react";
import Dialog from "@mui/material/Dialog";
import DialogContent from "@mui/material/DialogContent";
import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/icons-material/Close";
function MyDialog() {
const [show, setShow] = useState(true);
return (
<Dialog open={show}>
<DialogContent style={{ position: "relative" }}>
<IconButton
style={{ position: "absolute", top: "0", right: "0" }}
onClick={() => setShow(false)}
>
<CloseIcon />
</IconButton>
</DialogContent>
</Dialog>
);
}
I'm not using and DialogTitle in this example but you could do the same trick by setting style={{ position: "relative" }} for the DialogTitle and move the IconButton in it.
I usually control showing/hiding the dialog via the parent component and I pass the setter in props.
Upvotes: 3
Reputation: 628
I know this is an old question but I found it because I had the same issue. So for people like me Material-UI's Dialog-Demo lists an example with a close button:
import React from 'react';
import { createStyles, Theme, withStyles, WithStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import MuiDialogTitle from '@material-ui/core/DialogTitle';
import MuiDialogContent from '@material-ui/core/DialogContent';
import MuiDialogActions from '@material-ui/core/DialogActions';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import Typography from '@material-ui/core/Typography';
const styles = (theme: Theme) =>
createStyles({
root: {
margin: 0,
padding: theme.spacing(2),
},
closeButton: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1),
color: theme.palette.grey[500],
},
});
export interface DialogTitleProps extends WithStyles<typeof styles> {
id: string;
children: React.ReactNode;
onClose: () => void;
}
const DialogTitle = withStyles(styles)((props: DialogTitleProps) => {
const { children, classes, onClose, ...other } = props;
return (
<MuiDialogTitle disableTypography className={classes.root} {...other}>
<Typography variant="h6">{children}</Typography>
{onClose ? (
<IconButton aria-label="close" className={classes.closeButton} onClick={onClose}>
<CloseIcon />
</IconButton>
) : null}
</MuiDialogTitle>
);
});
const DialogContent = withStyles((theme: Theme) => ({
root: {
padding: theme.spacing(2),
},
}))(MuiDialogContent);
const DialogActions = withStyles((theme: Theme) => ({
root: {
margin: 0,
padding: theme.spacing(1),
},
}))(MuiDialogActions);
export default function CustomizedDialogs() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open dialog
</Button>
<Dialog onClose={handleClose} aria-labelledby="customized-dialog-title" open={open}>
<DialogTitle id="customized-dialog-title" onClose={handleClose}>
Modal title
</DialogTitle>
<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} color="primary">
Save changes
</Button>
</DialogActions>
</Dialog>
</div>
);
}
Upvotes: 3
Reputation: 235
I think you can also use Grid
(see tutorial here).
Something like
import Grid from '@material-ui/core/Grid';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
<DialogTitle>
<Grid container direction="row" justify="space-between" alignItems="center">
{myTitle}
<IconButton aria-label="close" onClick={closeDialog}>
<CloseIcon />
</IconButton>
</Grid>
</DialogTitle>
Upvotes: 9
Reputation: 531
For anyone looking for a solution using Material UI V4.
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
<DialogTitle id="id">
<Box display="flex" alignItems="center">
<Box flexGrow={1} >{title}</Box>
<Box>
<IconButton onClick={onClose}>
<CloseIcon />
</IconButton>
</Box>
</Box>
</DialogTitle>
Upvotes: 31
Reputation: 1282
I know this was asked pre Material UI V1 but the accepted answer works for Material UI version 0 (or whatever they called it).
For people wanting help with version 1 the MUI guys have exposed a <DialogTitle />
component that accepts a disableTypography
so you can customize your dialog.
EG
<Dialog open={this.state.show} onClose={this.onClose}>
<DialogTitle disableTypography className={styles.dialogTitle}>
<h2>Dialog...</h2>
<IconButton onClick={this.onClose}>
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent>
<span>Dialog Content</span>
</DialogContent>
</Dialog>
I just use flex with space between for the h2
and the Icon
.dialogTitle {
display: flex;
justify-content: space-between;
align-items: center;
}
Hope that helps somebody out. :-)
Upvotes: 51
Reputation: 104369
Put the image icon in the title, and use the css
to position it correctly, Try this:
Apply this css
on close image:
let closeImg = {cursor:'pointer', float:'right', marginTop: '5px', width: '20px'};
<Dialog
modal={false}
open={true}
title={
<div>
ABC
<img src='https://d30y9cdsu7xlg0.cloudfront.net/png/53504-200.png' style={closeImg}/>
</div>
}
>
Hello
</Dialog>
Check the working fiddle: https://jsfiddle.net/ve0qbgLr/
Upvotes: 24