TIL - HTML Dialog
Tags: html, beginners, tutorial, react
Published: 2021-05-17 19:02:24

# #TIL

Today I learned that HTML has a [native modal](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog), known as the  `<dialog>` element.

> The HTML <dialog> element represents a dialog box or other interactive component, such as a dismissible alert, inspector, or subwindow.

AN HTML POP UP? NO WAY! (yes way).

As always, I demonstrate the usage in React.js, which means that some functionality translates directly, and other functionality does not. For example, according to the docs: 

> The ::backdrop CSS pseudo-element can be used to style behind a <dialog> element when the dialog is displayed with HTMLDialogElement.showModal(). For example, to dim unreachable content behind the modal dialog.

As you will see in a moment, using  a `<dialog>` in React requires a little bit of a different usage to dim the background. But, truthfully I think it is still easier than with vanilla JS.

## The Modal

{% codesandbox 7qmo9%}

Looks great, doesn't it? And you will see in just a moment that the necessary code is relatively simple!

## The Code

```javascript 
import { useState } from "react";
import "./styles.css";

export default function App() {
  const [isOpen, setIsOpen] = useState(false);

  const openDialog = () => {
    setIsOpen(true);
  };

  const closeDialog = () => {
    setIsOpen(false);
  };
  return (
    <div className="App">
      <h1>HTMLs Native Dialog</h1>
      <h2>A simple modal</h2>

      {isOpen && (
        <>
          <div className="overlay" />
          <dialog open>
            <p>BOOM</p>
            <p>And just like that youve got a modal</p>
            <p>
              Easy peezy lemon squeezy{" "}
              <span role="img" aria-label="lemon emojis">
                🍋🍋🍋
              </span>
            </p>
            <button onClick={closeDialog}>Close</button>
          </dialog>
        </>
      )}
      <button className="open-btn" onClick={openDialog}>
        Open Dialog
      </button>
    </div>
  );
}
```

## Breaking it Down

The open or closed state of the modal is handled by the `useState` hook provided by React and toggled by the `openDialog()` and `closeDialog()` functions.

```javascript
import { useState } from "react";

...

const [isOpen, setIsOpen] = useState(false);

const openDialog = () => {
  setIsOpen(true);
};

const closeDialog = () => {
  setIsOpen(false);
};
```

The HTML for a `<dialog>` element looks something like:

```javascript
<dialog open>
  <p>BOOM</p>
  <p>And just like that youve got a modal</p>
  <p>
    Easy peezy lemon squeezy{" "}
    <span role="img" aria-label="lemon emojis">
      🍋🍋🍋
    </span>
  </p>
  <button onClick={closeDialog}>Close</button>
</dialog>
```
The most import part of the above code is the `open` property in the opening `<dialog>` tag, written as `<dialog open>`. That's how the browser knows to display the modal.

And the full `return` statement with the conditional render handled by the `isOpen` property in state.

```javascript
return (
    <div className="App">
      <h1>HTMLs Native Dialog</h1>
      <h2>A simple modal</h2>

      {isOpen && (
        <>
          <div className="overlay" />
          <dialog open>
            <p>BOOM</p>
            <p>And just like that youve got a modal</p>
            <p>
              Easy peezy lemon squeezy{" "}
              <span role="img" aria-label="lemon emojis">
                🍋🍋🍋
              </span>
            </p>
            <button onClick={closeDialog}>Close</button>
          </dialog>
        </>
      )}
      <button className="open-btn" onClick={openDialog}>
        Open Dialog
      </button>
    </div>
  );
```

## Why Should I Care?

The cool and most important thing about the `<dialog>` element is better accessibility. Sure, you can build your own modal, but then you've got to work extra hard to make it available to screen readers and other accessibility tools. 

Another cool benefit is not having to add a bunch of `z-index` properties to your CSS in order to properly display the modal and any overlays you wish to add. "Modal behaviour" is baked right into the `<dialog>` element. 

Added accessibility AND easier styling capabilities? Sounds like a WIN-WIN to me!

## The CSS

Curious how I personally styled my modal and overlay? Here is the full CSS file:

```css
.App {
  font-family: Arial, Helvetica, sans-serif;
  text-align: center;
  color: white;
  background-color: rgb(0, 0, 0);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
}

body {
  background-color: black;
}

dialog {
  margin-top: 8rem;
  width: 75%;
  color: white;
  background-color: black;
  border: 3px solid rgb(72, 70, 224);
}

button {
  background-color: rgb(72, 70, 224);
  color: white;
  border: none;
  padding: 0.5rem;
  border-radius: 0.5rem;
  cursor: pointer;
  font-size: 1rem;
  font-weight: bold;
}

button:hover {
  background-color: rgb(66, 247, 207);
  color: black;
}

.open-btn {
  width: 75%;
}

.overlay {
  position: fixed;
  margin: 0;
  top: 0;
  width: 100%;
  height: 100vh;
  background-color: rgba(9, 22, 39, 0.7);
}

@media only screen and (min-width: 500px) {
  dialog {
    width: 18rem;
  }

  .open-btn {
    width: 10rem;
  }
}
```

## The Overlay

The only thing I added that that doesn't come "baked in" was the overlay. I got creative with my solution, but I would not call it "difficult" or "complex". Inside my conditional render of the `<dialog>` element I added `<div className="overlay" />`. And simply styled with CSS:

```css
.overlay {
  position: fixed;
  margin: 0;
  top: 0;
  width: 100%;
  height: 100vh;
  background-color: rgba(9, 22, 39, 0.7);
}
```

Think of it as stretching a layer of slightly-transparent color across the entire screen when `isOpen` is `true`. 

## Conclusion

Check out this [great Shopify article](https://www.shopify.com/partners/blog/new-html) that features this and other useful HTML native elements. The `<dialog>` element is number 6 in the article and I really liked tihs part: 

> Does it work?
> The <dialog> does a slightly more complex thing…and does it well. Browser support is somewhat patchy (notably no Internet Explorer, and Safari is pending at the time of writing), but there is a polyfill.

> Is it accessible?
> Support is quite good, but it does need a little ARIA support to go to production. What's really good about the <dialog> element is that most accessibility support is built in, making it a far better starting point than having to create your own fixed inline custom dialog component.

I hope you enjoyed my article on this awesome HTML element! As always let me know if you have any questions, comments, feedback, suggestions, etc!

Thanks again and see you next time!

## Update

It appears that the `<dialog>` element does not behave as intended on iOS. At least not on mobile iOS. I am going to do some further digging and update this article with the relevant information as soon as possible!