2. NextJS: Create custom modal with TS and Tailwind CSS

We'll need a button to launch our custom modal, so when we click the "Open Modal" button, our custom modal should appear.

<button

className="rounded-md border h-10 px-4 text-white bg-blue-600 hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 

focus-visible:outline-blue-600"

type="button"

onClick={() => setModalClose(!modalClose)}>Open Modal</button>

We will create a state to manage the opening and closing of modal. By default the modal is closed.

'use client'
import { useState } from 'react'
...
const [modalClose, setModalClose] = useState(true);

Ok, now let's create our custom modal

Install a package clsx, it will help us dynamically add or remove className at run time based on state change.

npm i clsx

Following is modal <div></div>:

{/* Modal */}

      <div id="custom-modal" tab-index="-1" aria-hidden="true"

        className={clsx(

          "overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full",

          modalClose && "hidden")}

      >

        <div className="relative p-4 w-full max-w-2xl max-h-full mx-auto">

          {/* Modal content */}

          <div className="relative bg-white rounded-lg shadow dark:bg-gray-700">

            {/* Modal header */}

            <div className="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">

              <h3 className="text-xl font-semibold text-gray-900 dark:text-white">

                Modal Header

              </h3>

              <button type="button" className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"

                onClick={() => { setModalClose(!modalClose); }}

              >

                <svg className="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">

                  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />

                </svg>

                <span className="sr-only">Close modal</span>

              </button>

            </div>

            {/* Modal body */}

            <div className="p-4 md:p-5 space-y-4">

              Modal body goes here....

            </div>

            {/* Modal footer */}

            <div className="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">

              <button type="button" className="py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"

                onClick={() => { setModalClose(!modalClose); }}

              >Cancel</button>

              <button type="button" className="py-2.5 px-5 ms-3 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"

                onClick={() => { }}

              >Save</button>

            </div>

          </div>

        </div>

      </div>

Output:


Following is whole tsx file code just copy and paste to page.tsx file:

'use client'

import { useState } from 'react'

import clsx from 'clsx';


export default function Home() {

  const [modalClose, setModalClose] = useState(true);


  return (

    <>

      <button

        className="rounded-md border h-10 px-4 text-white bg-blue-600 hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"

        type="button"

        onClick={() => setModalClose(!modalClose)}

      >Open Modal</button>

      {/* Modal */}

      <div id="custom-modal" tab-index="-1" aria-hidden="true"

        className={clsx(

          "overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full",

          modalClose && "hidden")}

      >

        <div className="relative p-4 w-full max-w-2xl max-h-full mx-auto">

          {/* Modal content */}

          <div className="relative bg-white rounded-lg shadow dark:bg-gray-700">

            {/* Modal header */}

            <div className="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">

              <h3 className="text-xl font-semibold text-gray-900 dark:text-white">

                Modal Header

              </h3>

              <button type="button" className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"

                onClick={() => { setModalClose(!modalClose); }}

              >

                <svg className="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">

                  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />

                </svg>

                <span className="sr-only">Close modal</span>

              </button>

            </div>

            {/* Modal body */}

            <div className="p-4 md:p-5 space-y-4">

              Modal body goes here....

            </div>

            {/* Modal footer */}

            <div className="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">

              <button type="button" className="py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700"

                onClick={() => { setModalClose(!modalClose); }}

              >Cancel</button>

              <button type="button" className="py-2.5 px-5 ms-3 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"

                onClick={() => { }}

              >Save</button>

            </div>

          </div>

        </div>

      </div>

    </>

  );

}

Comments

Popular posts from this blog

Formatting MySQL Dates

SOAP Explained: With Javascript