Nitin Shinde
Nitin Shinde

Reputation: 1244

How can I add the close icon in the top right corner of the Material UI Dialog Header?

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:

Dialog with close button in top right corner

Upvotes: 46

Views: 109679

Answers (14)

ivkremer
ivkremer

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

190303458
190303458

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

Shani Kehati
Shani Kehati

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)
enter image description here

Upvotes: 0

stouch
stouch

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

Java wanna bee
Java wanna bee

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

Micha&#235;l Perrin
Micha&#235;l Perrin

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

gremo
gremo

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

Mike Dubs
Mike Dubs

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

Raph
Raph

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

Paul
Paul

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

Kerial
Kerial

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

dotNet Decoder
dotNet Decoder

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

Kurtis
Kurtis

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

Mayank Shukla
Mayank Shukla

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

Related Questions