MUI(React×Material-ui)で共通部品として使えるモーダルダイアログを作る

2022年4月24日日曜日

react

t f B! P L

Material-ui で提供されている Dialog コンポーネントは、それ自体が便利なダイアログコンポーネントであるが、閉じるボタンなどの実装は各自で実装する必要がある。

そこで、閉じるボタンや、スマホなどの画面サイズが小さいデバイスの時にフルスクリーンで表示する機能など、ある程度共通的な機能をまとた部品を今回は作ってみる。

完成イメージ

今回作る部品の完成イメージは次のとおり。モーダルダイアログのタイトルと閉じるボタン(×)は共通側で実装し、コンテンツ部分のみ個別に実装する方式とする。

enter image description here

また、スマホなどの横幅が狭いデバイスで表示された場合は、フルスクリーンでダイアログを表示するようにしている。

enter image description here

ダイアログ部品の実装

まず、共通部品となるダイアログ部品を作る。

import React, { useEffect, useState } from 'react';
import CloseIcon from '@mui/icons-material/Close';
import {
  Dialog, DialogContent,
  DialogTitle,
  IconButton,
  useMediaQuery
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
import PropTypes from 'prop-types';

/**
 * タイトルエリアのスタイル
 */
const titleStyle = {
  display: "flex",
  justifyContent: "space-between",
  alignItems: "center",
  backgroundColor: '#333',
  '& *': {
    fontWeight: 'bold',
    color: '#fff'
  }
}

function ModalDialog(props: any) {

  // プロパティ
  const {
    title,
    onClose,
    open,
    maxWidth,
  } = props;

  // ダイアログ表示状態
  const [dialogOpen, setDialogOpen] = useState(false);
  const theme = useTheme();
  const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));

  // openの値が変化した時
  useEffect(() => setDialogOpen(open), [open]);

  // ダイアログクローズ
  const handleClose = () => {
    setDialogOpen(false);
    onClose();
  };

  return (
    <Dialog
      open={dialogOpen}
      fullWidth={true}
      fullScreen={fullScreen}
      maxWidth={maxWidth}>
      <DialogTitle sx={{ ...titleStyle }}>
        <span>{title}</span>
        <IconButton aria-label="close" onClick={handleClose}>
          <CloseIcon />
        </IconButton>
      </DialogTitle>
      <DialogContent>
        {props.children}
      </DialogContent>
    </Dialog>
  );
}

// プロパティ
ModalDialog.propTypes = {
  title: PropTypes.string.isRequired,
  onClose: PropTypes.func.isRequired,
  open: PropTypes.bool.isRequired,
  children: PropTypes.element,
  maxWidth: PropTypes.string
};

export default ModalDialog;

作ったダイアログ部品を使う

次に、上で作成したダイアログ部品を使って、モーダルダイアログを実装する。

ソースコードは次のとおり、ダイアログに表示するコンテンツは、ModalDialog の子要素に書けばいい。

import { Box, Stack, TextField } from '@mui/material';
import Button from '@mui/material/Button';
import React, { useState } from 'react';
import ModalDialog from './dialog/ModalDialog';

function Sample() {

  // ダイアログ用のstate
  const [digOpen, setDigOpen] = useState(false);

  return (
    <div>
      <ModalDialog
        title="タイトル"
        open={digOpen}
        onClose={() => setDigOpen(false)}>
        <Box sx={{ mt: 2 }}>
          <Stack spacing={2}>
            <TextField
              label="ID"
              variant="filled"
            />
            <TextField
              label="Password"
              variant="filled"
            />
          </Stack>
          <Box sx={{ mt: 3 }}>
            <Button variant="contained">ログイン</Button>
          </Box>
        </Box>
      </ModalDialog>
      <Button onClick={() => setDigOpen(true)}>
        モーダル表示
      </Button>
    </div>
  );
}

export default Sample;

まとめ

ここまでの内容で、共通的に使えるダイアログ部品は完成だ。

SPAアプリなどでは、ダイアログを使った画面をよく実装するため、今日つ部品としてまとめておくと便利である。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ