Modal
Modals are essential UI elements for displaying messages, forms, or confirmations without navigating away from the current page. In this guide, you'll learn how to build a clean, responsive, and reusable modal component using Tailwind CSS in a Next.js (or React.js) application. Whether you're creating a login popup or a custom alert, this tutorial will help you do it efficiently.
Modal preview
Please install everything that's required
Before setup and using this component, please install all the required dependencies from this link (if you have never installed).
1. Setup codes
1.1. Setup Button components
First you need setup Button components in my docs.
1.2. Setup Modal components
Create a new component components/ui/Modal.tsx
jsx"use client"; import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from "@headlessui/react"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import Button from "./Button"; const Modal = ({ open, setOpen }) => { return ( <Dialog open={open} onClose={setOpen} className="relative z-10"> <DialogBackdrop transition className="data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in fixed inset-0 bg-gray-500/75 transition-opacity" /> <div className="fixed inset-0 z-10 w-screen overflow-y-auto"> <div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"> <DialogPanel transition className="data-closed:translate-y-4 data-closed:opacity-0 data-enter:duration-300 data-enter:ease-out data-leave:duration-200 data-leave:ease-in data-closed:sm:translate-y-0 data-closed:sm:scale-95 relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6" > <div className="sm:flex sm:items-start"> <div className="mx-auto flex size-12 shrink-0 items-center justify-center rounded-full bg-red-100 sm:mx-0 sm:size-10"> <ExclamationTriangleIcon aria-hidden="true" className="size-6 text-red-600" /> </div> <div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left"> <DialogTitle as="h3" className="text-base font-semibold text-gray-900"> Are you sure you want to delete this project? </DialogTitle> <div className="mt-2"> <p className="text-sm text-gray-500"> This action cannot be undone. Deleting this project will permanently remove all of its data. Please confirm if you wish to proceed. </p> </div> </div> </div> <div className="mt-5 sm:mt-4 sm:flex sm:justify-end sm:gap-2"> <Button variant="secondary" onClick={() => setOpen(false)}> Cancel </Button> <Button onClick={() => setOpen(false)} className="bg-system-error"> Delete </Button> </div> </DialogPanel> </div> </div> </Dialog> ); }; export default Modal;
2. Usages
You can create a state and pass into the Modal component.
jsx"use client"; import React, { useState } from "react"; import Button from "@/components/Button"; import Modal from "@/components/Modal"; const PreviewModal = () => { const [open, setOpen] = useState(false); return ( <div className="flex justify-center rounded-lg border border-gray-300 py-14"> <Button onClick={() => setOpen(true)}>Open modal</Button> <Modal open={open} setOpen={setOpen} /> </div> ); }; export default PreviewModal;