Source

stories/Modal.jsx

/** @module Modal */
import React from 'react';
import Button from './Button';
import PropTypes from 'prop-types';
import { Dialog, DialogActions, DialogContent, IconButton, Typography } from '@mui/material';
import { Close } from '@mui/icons-material';

/**
 * Wrapper of the Mui Dialog component
 * Prevent closing by clicking outside of the dialog by NOT passing in a handleClose prop
 * @function
 * @param {object} props
 * @param {boolean} props.open - whether the dialog is open or not
 * @param {string} [props.title] - the title of the dialog
 * @param {string} [props.okLabel] - the label for the OK button
 * @param {boolean} [props.disableOk] - disable the OK button
 * @param {string} [props.cancelLabel] - the label for the Cancel button
 * @param {boolean} [props.disableCancel] - disable the OK button
 * @param {boolean} [props.showX] - whether to show the X in the top right corner
 * @param {boolean} [props.hideActions] - whether to hide the actions (OK and Cancel buttons)
 * @param {boolean} [props.hideCancel] - whether to hide the Cancel button
 * @param {boolean} [props.hideOk] - whether to hide the OK button
 * @param {function} [props.onOk] - the function to call when the OK button is clicked
 * @param {function} [props.onCancel] - the function to call when the Cancel button is clicked
 * @param {function} [props.handleClose] - the function to call when the dialog is closed
 * @param {string} [props.okColor] - the color of the OK button
 * @param {string} [props.cancelColor] - the color of the Cancel button
 * @returns {React.ReactElement} - React component
 */
const Modal = ({
  open, okLabel, cancelLabel, title, onOk, onCancel, handleClose, showX, children, hideActions, hideCancel, hideOk,
  disableOk, disableCancel, okColor = 'primary', cancelColor = 'regressive', ...props
}) => {
  const titleRender = () => {
    if (showX) {
      return (
        <>
          <IconButton
            aria-label="close"
            onClick={handleClose}
            sx={{
              position: 'absolute',
              right: 8,
              top: 8,
              color: (theme) => theme.palette.grey[500],
            }}
          >
            <Close />
          </IconButton>
          {title}
        </>
      );
    }

    return <>{title}</>;
  };

  return (
    <Dialog
      open={open}
      onClose={handleClose}
      {...props}
      aria-labelledby="alert-dialog-title"
      aria-describedby="alert-dialog-description"
    >
      <Typography id="alert-dialog-title" variant="modalTitle">{titleRender()}</Typography>
      <DialogContent>{children}</DialogContent>
      {hideActions ? null : (
        <DialogActions>
          <ShowHidden hide={hideCancel} disabled={disableCancel} onClick={onCancel} label={cancelLabel || 'Cancel'} color={cancelColor}/>
          <ShowHidden hide={hideOk} disabled={disableOk} onClick={onOk} autoFocus label={okLabel || 'Ok'} color={okColor} />
        </DialogActions>
      )
      }
    </Dialog>
  );
};

Modal.propTypes = {
  open: PropTypes.bool.isRequired,
  showX: PropTypes.bool,
  okLabel: PropTypes.string,
  disableOk: PropTypes.bool,
  cancelLabel: PropTypes.string,
  disableCancel: PropTypes.bool,
  title: PropTypes.string,
  children: PropTypes.node,
  onOk: PropTypes.func,
  onCancel: PropTypes.func,
  handleClose: PropTypes.func,
  hideActions: PropTypes.bool,
  hideCancel: PropTypes.bool,
  hideOk: PropTypes.bool,
  okColor: PropTypes.string,
  cancelColor: PropTypes.string,
  // Mui Dialog props (...props)
  // by defining them here, they will be consumed by Storybook for use in the controls area
  fullWidth: PropTypes.bool,
  maxWidth: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
};

/**
 * @function
 * @param {object} props - props object
 * @param {boolean} props.hide - whether to hide the button or not
 * @param {object} props.props - props for the Button component
 * @returns {React.ReactElement | null} - React component
 */
const ShowHidden = ({ hide, ...props }) => {
  return hide ? null :
    (
      <Button {...props} />
    );
};
ShowHidden.propTypes = {
  hide: PropTypes.bool
};

export default Modal;