Best Practices to Create a Modal Component with React and Tailwind CSS

Modals are essential components in SaaS applications (dashboards, CMS, LMS). It is used for confirmations, alerts, or additional interactions. A well-designed modal can enhance user experience while maintaining a clean and reusable codebase.

In this guide, I’ll show you how to create a reusable modal component using React and Tailwind CSS. We’ll follow best React practices by first building a customizable wrapper component for the modal, which will help us create a basic outline (overlay + close button) for each modal component.

Whether you're building a project/SaaS for yourself or a client, or you want to enhance your design system, this guide will help you simplify modal management in your React projects.

React Tailwind Modal Component Features

  • Reusable Design: The ModalWrapper component provides a versatile base for any modal type.
  • Close Button: A cross icon to close the modal.
  • Customizable Children: Easily pass any content as children to fit your requirements.

Delete Modal Component UI

Here’s how the tailwind delete modal looks like:

Tailwind delete modal component Preview

It includes:

  • A semi-transparent background overlay.
  • A close icon in the top-right corner.
  • Title to explain the modal action.
  • Action buttons for "Delete" and "Cancel."

React Tailwind Modal Component Code

Below is the implementation of the React modal, I divided into three sections for clarity.

1. Modal Wrapper Component in React

Why create this?

The ModalWrapper acts as a base structure for all modals. It handles the overlay and ensures consistent styling across different modals in your app.

It accespts children as props, we can create any modal content of out it. We don't have to repeat the code for basic styling everytime.

1import { X } from 'lucide-react' 2import React from 'react' 3 4type ModalWrapperProps = { 5 children: React.ReactNode 6 onClose: () => void 7} 8 9const ModalWrapper: React.FC<ModalWrapperProps> = ({ children, onClose }) => { 10 return ( 11 <div className="fixed inset-0 z-[9999] flex h-full w-full items-center justify-center bg-black bg-opacity-50"> 12 <div className="relative min-h-[200px] w-[40%] max-w-md rounded-2xl bg-white p-10 shadow-lg sm:w-11/12 sm:p-8"> 13 <button 14 className="absolute right-4 top-4 text-gray-500 hover:text-gray-800" 15 onClick={onClose} 16 aria-label="Close" 17 > 18 <X size={24} /> 19 </button> 20 {children} 21 </div> 22 </div> 23 ) 24} 25 26export default ModalWrapper

2. Delete Modal Component with Tailwind CSS

This modal is specifically for confirmations before delete an item from an app. It uses the ModalWrapper to display its content and actions.

1import React from 'react' 2import ModalWrapper from './ModalWrapper' 3 4interface DeleteModalProps { 5 handleDeleteModal: () => void 6} 7 8const DeleteModal: React.FC<DeleteModalProps> = ({ handleDeleteModal }) => { 9 return ( 10 <ModalWrapper onClose={handleDeleteModal}> 11 <div className="mx-auto max-w-72"> 12 <p className="text-center text-xl font-extrabold leading-relaxed text-black"> 13 Are you sure you want to delete this task? 14 </p> 15 <div className="mt-6 flex justify-center gap-6"> 16 <button 17 className="rounded-xl bg-[#713FFF] px-7 py-2 text-base font-semibold text-white shadow-lg" 18 onClick={handleDeleteModal} 19 > 20 Delete 21 </button> 22 <button 23 className="rounded-xl border border-[#d8e0f0] bg-white px-7 py-2 text-base font-normal text-[#7d8592] shadow-sm" 24 onClick={handleDeleteModal} 25 > 26 Cancel 27 </button> 28 </div> 29 </div> 30 </ModalWrapper> 31 ) 32} 33 34export default DeleteModal

3. How to Use in a Parent Component

Here’s an example of how to use the DeleteModal in your application:

We are showing a modal using an "Open Modal" button in the UI. This is only for the demonstration purposes.

1import React, { useState } from 'react' 2import Button from './components/Button' 3import DeleteModal from './components/Modal/DeleteModal' 4 5const App: React.FC = () => { 6 const [showModal, setShowModal] = useState(false) 7 8 const handleDeleteModal = () => { 9 setShowModal(!showModal) 10 } 11 12 return ( 13 <div className="flex h-[100vh] w-full items-center justify-center"> 14 <Button onClick={handleDeleteModal}>Delete Task</Button> 15 16 {showModal && <DeleteModal handleDeleteModal={handleDeleteModal} />} 17 </div> 18 ) 19} 20 21export default App

Did it help? Let me know via LinkedIn, I would happy to have your feedback.


Flexy UI Newsletter

Build better and faster UIs.Get the latest components and hooks directly in your inbox. No spam!