Personal Blog

Another way to create modals in react using the HTML dialog element

10/25/2022, 6:00 AM

Introduction

Modals are a frequent UI element in our applications, in fact, I would say all the applications I have coded have some sort of modals on them.

And when it comes to how to code them, we usually tend to use a UI element (Bootstrap, Material UI, etc.) or develop our own implementation in plain React, but did you know that there's a standard HTML element called dialog to display modals?

Why use the standard dialog element

Using the standard dialog element gives us several advantages over doing our own implementation, advantages like:

  • It's widely available (92% of browsers support it at the moment)

  • accessibility out of the box This element already implements the most basic fundamental of accessibility for HTML dialogs

  • standard HTML element Which mean that this element is not going away anytime soon, thus making our application a bit more future-proof

  • less code Because we won't need to use the aria-* properties anymore, and also we don't need custom logic to render the modal outside the root component by using a React.createPortal

Using dialog in your application

Adding the dialog element to our component

In our React component, we just need to add a dialog element with the content we want

<dialog>
  <form method="dialog">
    <section>
      <label htmlFor="name">Name: </label>
      <input name="name" placeholder="Type your name" />
    </section>
    <section>
      <label htmlFor="email">Email: </label>
      <input name="email" placeholder="Type your email" />
    </section>
    <menu>
      <button id="cancel">
        Cancel
      </button>
      <button type="submit">Submit</button>
    </menu>
  </form>
</dialog>

  • method="dialog"

Basically tells our application that when the form gets submitted, the modal needs to be close automatically

Accessing the dialog element on React

To do this, we will use the useRef hook

import React, { useRef } from "react";
function App() {
  const dialogRef = useRef();

  return (
      <dialog ref={dialogRef}>
          {/*...dialog content...*/}
      </dialog>
  )
}

Add a button to show the modal

Let's add a button in our React component that once is called it will call the showModal function to open the modal

import React, { useRef } from "react";

function App() {
  const dialogRef = useRef();

  const showModal = () => {
    dialogRef.current.showModal();
  }
  
  return (
      <>
        <dialog ref={dialogRef}>
            {/*...dialog content...*/}
        </dialog>
        <button onClick={showModal}>Show Modal</button>
      </>
  )

Handling form submit

Now the only things left is to handle the onSubmit event, so let's create a new function on the React Component to handle and get all the values from the form inside the modal

const onSubmit = (e) => {
  console.log({
    name: e.target.name.value,
    email: e.target.email.value
  })
}

Final code

Let's add a function to close the modal and that will be the final code

import React, { useRef } from "react";

function App() {
  const dialogRef = useRef();

  const openModal = () => {
    dialogRef.current.showModal();
  };

  const onCancel = () => {
    dialogRef.current.close();
  };

  const onSubmit = (e) => {
    console.log({
      name: e.target.name.value,
      email: e.target.email.value,
    });
  };

  return (
    <>
      <dialog ref={dialogRef}>
        <form method="dialog" onSubmit={onSubmit}>
          <section>
            <label htmlFor="name">Name: </label>
            <input name="name" placeholder="Type your name" />
          </section>
          <section>
            <label htmlFor="email">Email: </label>
            <input name="email" placeholder="Type your email" />
          </section>
          <menu>
            <button onClick={onCancel}>Cancel</button>
            <button type="submit">Confirm</button>
          </menu>
        </form>
      </dialog>

      <button onClick={openModal}>Show Modal</button>
    </>
  );
}

export default App;

Styling

To style our dialog we can use normal CSS properties, the only relevant and special thing is that if you want to change the background behind the modal you can use the pseudo-element ::backdrop, example:

dialog::backdrop {
  background: rgba(0, 0, 0, 0.7);
}

Polyfill

If you want to support browsers like Internet Explorer or old versions of Chrome, you will need to add this polyfill to your page: https://github.com/GoogleChrome/dialog-polyfill

Profile Picture

Miguel

I'm a Senior Software Engineer working in Berlin, primary focused on Frontend Technologies but also interested in Backend with Go, Terminal Apps and Neovim.

More posts

Debugging Javascript applications with Neovim

My notes of how to compile a typescript library

How to create a basic implementation of React Hook Form

How to render pretty code blocks using Contentful Rich Text Editor and Gatsby

Extending Contentful Rich Text editor to render Youtube embed videos

© 2023 • Built with Gatsby