HTML Dialog Element with React.js and Tailwind CSS

Recently, I've tried to work with the new <dialiog /> Element in React.js. I like how minimal the API and the React.js code is. For simple pop-ups and modals, it works great. I have some doubt when it gets more complex, for example if you add a prev or next button, but it should be realizable.

The styling is done quite well. In basic CSS, you can target the open dialog with dialog[open] {} and the background with dialog[open]::backdrop {}. Everything else are just usual HTML Elements.

Browser Support

Image of Table, which shows in which desktop browsers the element is supported.

The <dialog /> Element is supported in all relevant browsers.

Image of Table, which shows in which mobile browsers the element is supported.

Same for all relevant mobile browsers.

Source: https://caniuse.com/mdn-html_elements_dialog

Example

Here is my minimal version of the implementation for Next.js with Tailwind CSS:

"use client";

import { useRef } from "react";

import { P } from "@/components/ui";
import { Image } from "@/components/image";

type Props = {
  children: string;
  image: {
    src: string;
    alt: string;
    width: number;
    height: number;
  };
};

export function GalleryItem({ children, image }: Props): JSX.Element {
  const ref = useRef<HTMLDialogElement>(null);

  function openModal() {
    ref.current?.showModal();
  }

  function closeModal() {
    ref.current?.close();
  }

  return (
    <div>
      <div className="h-64 shadow shadow-black cursor-pointer overflow-hidden rounded-xl">
        <Image
          className="w-full h-full align-middle object-cover ease-linear duration-300 sm:hover:scale-125"
          src={image.src}
          width={500}
          height={500}
          alt={image.alt}
          onClick={openModal}
        />
      </div>
      <dialog
        ref={ref}
        onClick={closeModal}
        className="focus:outline-none focus:ring focus:ring-neutral-500 rounded-xl backdrop:bg-neutral-800 backdrop:bg-opacity-85"
      >
        <Image
          className="w-full h-full"
          src={image.src}
          width={image.width}
          height={image.height}
          alt={image.alt}
        />
        <div className="absolute bottom-0 h-1/3 w-full bg-gradient-to-t from-neutral-800 p-4 flex items-end">
          <P className=" text-white p-0">{children}</P>
        </div>
      </dialog>
    </div>
  );
}

9/100 of #100DaysToOffload

#development #react #javascript #typescript #tailwind

Discuss...