LoginSignup
1
2

Next.jsとTailwind CSSでダイアログボックスを秒で実装する

Last updated at Posted at 2024-01-30

この記事で分かること

  • Next.jsとTailwind CSSでのダイアログボックス(モーダル)の実装方法

全ソースコードはこちら

実行結果

no_modal.png

modal.png

機能概要

  • Open Modalをクリックするとダイアログが開く
  • ダイアログはOKをクリックするかダイアログの外をクリックすると閉じる
  • メッセージは固定

実装コード

ダイアログボックスコンポーネント

  • src/app/components/Modal.tsx
import React from 'react';

export type ModalProps = {
  open: boolean;
  onCancel: () => void;
  onOk: () => void;
};

const Modal = (props: ModalProps) => {
  return props.open ? (
    <>
      <div className="bg-white  top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-80 h-48 p-5 flex flex-col items-start absolute z-20">
        <h1 className="text-xl font-bold mb-5">Title</h1>
        <p className="text-lg mb-5">Dialog Message.</p>
        <div className="flex mt-auto w-full">
          <button
            className="bg-slate-900 hover:bg-slate-700 text-white px-8 py-2 mx-auto"
            onClick={() => props.onOk()}
          >
            OK
          </button>
        </div>
      </div>
      <div
        className="fixed bg-black bg-opacity-50 w-full h-full z-10"
        onClick={() => props.onCancel()}
      ></div>
    </>
  ) : (
    <></>
  );
};

export default Modal;

呼び出し側

  • src/app/page.tsx
'use client';

import MessageDialog from './components/Modal';
import { useState } from 'react';

export default function Home() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <MessageDialog
        open={isOpen}
        onCancel={() => setIsOpen(false)}
        onOk={() => setIsOpen(false)}
      />

      <div className="flex flex-col min-h-screen items-center justify-center">
        <button
          className="bg-slate-900 hover:bg-slate-700 text-white text-lg w-60 h-14 py-2 px-4"
          onClick={() => setIsOpen(true)}
        >
          Open Modal
        </button>
      </div>
    </>
  );
}

フォルダ構成(抜粋)

src
  └─ app
      ├─ components
      │   └─ Modal.tsx
      └─ page.tsx

ポイント

  • ダイアログはabsoluteを指定することで、元の画面の上に重なるように表示する
  • absoluteの次にfixeddivを指定することで、背景を半透明を実現し、クリック判定を持たせる
  • ダイアログにz-20、ダイアログの周囲にz-10のZインデックスを指定し、ダイアログが全面に来るようにする
  • 呼び出し元はuseState()isOpenフラグを設定する
  • useStateを使用するためClient Side Rendering('use client';)を指定する必要がある
  • propsでメッセージ等を渡すようにすれば、ダイアログの表示を可変にできる
  • ダイアログの<div>className="shadow-2xl""rounded"などを指定するともう少しカッコよくなる
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2