react typescript tailwind css popup modal tutorial

React TypeScript Tailwind CSS Popup Modal Tutorial

February 27, 2024 By Aaronn

In this tutorial, we'll create a popup modal in your React TypeScript project using Tailwind CSS. Before you begin, ensure your project has React, TypeScript, and Tailwind CSS installed and configured.

Install & Setup Tailwind CSS + React 18+ Typescript + Vite


React TypeScript Simple Popup Modal with Tailwind CSS

Create a new file named Modal.tsx in your src/components folder.

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

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
}

const Modal: React.FC<ModalProps> = ({ isOpen, onClose }) => {
  if (!isOpen) {
    return null;
  }

  return (
    <div className="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
      <div className="bg-white p-8 rounded w-96 text-center">
        <h2 className="text-2xl font-bold mb-4">Modal Content</h2>
        <p>This is the content of the modal.</p>
        <button
          className="mt-4 bg-red-500 hover:bg-red-700 text-white py-2 px-4 rounded"
          onClick={onClose}
        >
          Close Modal
        </button>
      </div>
    </div>
  );
};

export default Modal;

Update your src/App.tsx file to import and use the Modal.tsx component.

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

const App: React.FC = () => {
  const [isModalOpen, setModalOpen] = useState(false);

  const openModal = () => {
    setModalOpen(true);
  };

  const closeModal = () => {
    setModalOpen(false);
  };

  return (
    <div className="min-h-screen flex items-center justify-center">
      <button
        className="bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
        onClick={openModal}
      >
        Open Modal
      </button>

      <Modal isOpen={isModalOpen} onClose={closeModal} />
    </div>
  );
};

export default App;
react typescript tailwind popup modal

react typescript tailwind popup modal

React TypeScript Tailwind CSS Popup Modal Outside Click to Close

Create a React modal component with TypeScript and Tailwind CSS. Include a close button, implement outside click functionality, and add a cross SVG icon.

Create a reusable CloseButton.tsx component:

// src/components/CloseButton.tsx
import React from 'react';

interface CloseButtonProps {
  onClick: () => void;
}

const CloseButton: React.FC<CloseButtonProps> = ({ onClick }) => (
  <button
    className="absolute top-4 right-4 text-gray-600 hover:text-gray-800"
    onClick={onClick}
  >
    <svg
      xmlns="http://www.w3.org/2000/svg"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
      className="h-6 w-6"
    >
      <path
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth={2}
        d="M6 18L18 6M6 6l12 12"
      />
    </svg>
  </button>
);

export default CloseButton;

Update the Modal component to use the CloseButton.tsx and handle outside click:

// src/components/Modal.tsx
import React, { useEffect, useRef } from 'react';
import CloseButton from './CloseButton';

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  children: React.ReactNode; 
}

const Modal: React.FC<ModalProps> = ({ isOpen, onClose, children }) => {
  const modalRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleOutsideClick = (event: MouseEvent) => {
      if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
        onClose();
      }
    };

    if (isOpen) {
      document.addEventListener('mousedown', handleOutsideClick);
    }

    return () => {
      document.removeEventListener('mousedown', handleOutsideClick);
    };
  }, [isOpen, onClose]);

  return (
    <>
      {isOpen && (
        <div className="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
          <div ref={modalRef} className="bg-white p-8 rounded w-96 relative text-center">
            <CloseButton onClick={onClose} />
            {children}
          </div>
        </div>
      )}
    </>
  );
};

export default Modal;

Update the App.tsx file to use the enhanced Modal.tsx component:

// src/App.tsx
import React, { useState } from 'react';
import Modal from './components/Modal';

const App: React.FC = () => {
  const [isModalOpen, setModalOpen] = useState(false);

  const openModal = () => {
    setModalOpen(true);
  };

  const closeModal = () => {
    setModalOpen(false);
  };

  return (
    <div className="min-h-screen flex items-center justify-center">
      <button
        className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
        onClick={openModal}
      >
        Open Modal
      </button>

      <Modal isOpen={isModalOpen} onClose={closeModal}>
        <h2 className="text-2xl font-bold mb-4">Modal Content</h2>
        <p>This is the content of the modal.</p>
        <button
          className="mt-4 bg-red-500 hover:bg-red-700 text-white py-2 px-4 rounded"
          onClick={closeModal}
        >
          Close Modal
        </button>
      </Modal>
    </div>
  );
};

export default App;
react typescript tailwind popup modal with icon

react typescript tailwind popup modal with icon

React TypeScript Tailwind CSS Confirmation Modal

Create a reusable CloseButton.tsx component:

// src/components/CloseButton.tsx
import React from 'react';

interface CloseButtonProps {
  onClick: () => void;
}

const CloseButton: React.FC<CloseButtonProps> = ({ onClick }) => (
  <button
    className="absolute top-4 right-4 text-gray-600 hover:text-gray-800"
    onClick={onClick}
  >
    <svg
      xmlns="http://www.w3.org/2000/svg"
      fill="none"
      viewBox="0 0 24 24"
      stroke="currentColor"
      className="h-6 w-6"
    >
      <path
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth={2}
        d="M6 18L18 6M6 6l12 12"
      />
    </svg>
  </button>
);

export default CloseButton;

Create a new component named ConfirmationModal.tsx:

// src/components/ConfirmationModal.tsx
import React from 'react';
import CloseButton from './CloseButton';

interface ConfirmationModalProps {
  isOpen: boolean;
  onClose: () => void;
  onConfirm: () => void;
}

const ConfirmationModal: React.FC<ConfirmationModalProps> = ({ isOpen, onClose, onConfirm }) => {
  return (
    <>
      {isOpen && (
        <div className="fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center">
          <div className="bg-white p-8 rounded w-96 relative">
            <CloseButton onClick={onClose} />

            <h2 className="text-2xl font-bold mb-4">Confirmation</h2>
            <p>Are you sure you want to perform this action?</p>

            <div className="flex justify-between mt-4">
              <button
                className="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mr-2"
                onClick={onClose}
              >
                Cancel
              </button>
              <button
                className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
                onClick={() => {
                  onConfirm();
                  onClose();
                }}
              >
                Confirm
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
};

export default ConfirmationModal;

Update the App.tsx file to use the ConfirmationModal component:

// src/App.tsx
import React, { useState } from 'react';
import ConfirmationModal from './components/ConfirmationModal';

const App: React.FC = () => {
  const [isConfirmationModalOpen, setConfirmationModalOpen] = useState(false);

  const openConfirmationModal = () => {
    setConfirmationModalOpen(true);
  };

  const closeConfirmationModal = () => {
    setConfirmationModalOpen(false);
  };

  const handleConfirm = () => {
    console.log('Confirmed!');
    // Add your confirmation logic here
  };

  return (
    <div className="min-h-screen flex items-center justify-center">
      <button
        className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
        onClick={openConfirmationModal}
      >
        Open Confirmation Modal
      </button>

      <ConfirmationModal
        isOpen={isConfirmationModalOpen}
        onClose={closeConfirmationModal}
        onConfirm={handleConfirm}
      />
    </div>
  );
};

export default App;
react typescript tailwind dialog modal

react typescript tailwind dialog modal

Related Posts

How to Use Toastify in React with Tailwind CSS

React with Tailwind CSS File Upload Example

React Tailwind CSS Forgot Password Example

Create a Responsive Navbar React Tailwind CSS TypeScript

How to Add Drag-and-Drop Image Upload with Dropzone in React Using Tailwind CSS