DEV Community

Cover image for How they made controls at Github? Modal dialog
Kiran Mantha
Kiran Mantha

Posted on • Updated on

How they made controls at Github? Modal dialog

Recap

In previous episode we saw how to create a dropdown using details and summary tags.

Present

In this episode let's see how to create a modal dialog out of details and summary tags.

When we say modal dialog, it should contain 2 main things.

  1. an overlay
  2. a container to display content

let's start with html

<details role='dialog'>
    <summary>click me to open a dialog</summary>
    <div>I'm in a dialog. click outside to close me.</div>
</details>
Enter fullscreen mode Exit fullscreen mode

when rendered, this displays in an accordion fashion. so let's style it to look like a dialog.

:root {
  --border-color: #ccc;
  --spacing: 1rem;
  --primary: #fff;
}

details[role='dialog'] {
  display: inline-block;

  summary {
    cursor: pointer;
    border: 1px solid var(--border-color);
    padding: 10px;
  }

  summary + div {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    margin: calc(var(--spacing) * 2) auto;
    width: 500px;
    background-color: var(--primary);
    z-index: 2;
    padding: var(--spacing);
  }
}
Enter fullscreen mode Exit fullscreen mode

all is good. The dialog says click outside to close me. heck but where is the overlay?? ๐Ÿ˜•
you know the secret sauce for this in last episodeโ—โ—

tadaaaaa

  &[open] summary {
    &::before {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 1;
      display: block;
      cursor: default;
      content: ' ';
      background-color: rgba(0, 0, 0, 0.5);
    }
  }
Enter fullscreen mode Exit fullscreen mode

yeahh got it?? but small change. In last episode, the background-color of summary tag is transparent but here in order to give user a sense of overlay we slapped color to background.

Now let's see the entire css:

:root {
  --border-color: #ccc;
  --spacing: 1rem;
  --primary: #fff;
}

details[role='dialog'] {
  display: inline-block;

  summary {
    cursor: pointer;
    border: 1px solid var(--border-color);
    padding: 10px;
  }

  &[open] summary {
    &::before {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 1;
      display: block;
      cursor: default;
      content: ' ';
      background-color: rgba(0, 0, 0, 0.5);
    }
  }

  summary + div {
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    margin: calc(var(--spacing) * 2) auto;
    width: 500px;
    background-color: var(--primary);
    z-index: 2;
    padding: var(--spacing);
  }
}
Enter fullscreen mode Exit fullscreen mode

That's it. see how simple it is to create a modal dialog?? But this implementation got its own caveats:

  1. you can't stop closing the dialog when user clicks outside. So if you intend to use it, then use it for info dialogs where you just display some static content.

Protips

Tip:1

when you say modal dialog, you need some handlers to do some actions after dialog opens and after it is closed. Don't worry i got you covered. Details tag has ontoggle event which helps us in such scenerios.

detailsTag.addEventListener('toggle', () => {
  if(detailsTag.open) {
    // do operation when dialog opens
  } else {
    // do operation when dialog closed
  }
})
Enter fullscreen mode Exit fullscreen mode

Tip:2

let's say you need to disable backdrop click to close the dialog. In that case, add a data attribute data-disableBackdropClick to summary tag and add a little more css to summary tag when dialog has open attribute. this is how the html and css looks:

<details id='backdropDetails' role="dialog">
    <summary data-disableBackdropClick="true">click to open a dialog</summary>
    <div>
      i'm in a dialog. i cannot be closed by clicking outside and need javascript to close me.
      <button id='modalCloseButton'>close me</button>
    </div>
</details>
Enter fullscreen mode Exit fullscreen mode
....
&[open] summary[data-disableBackdropClick="true"] {
   pointer-events: none;
}
....
Enter fullscreen mode Exit fullscreen mode

that's it. now try to click outside the modal. it won't close. Now how to close this dialog. At last we need some javascript to get this done.

const closeButton = document.getElementById('modalCloseButton'),
  backdropDetails = document.getElementById('backdropDetails');

closeButton.onclick = function () {
  backdropDetails.open = false;
};
Enter fullscreen mode Exit fullscreen mode

yayyyy. now whenever you click on that button, the modal will close but it will not close when you click outside of modal.

Asusual you can find the working example here.

See you in next episode. Thanks..
Kiran ๐Ÿ‘‹

Top comments (1)

Collapse
 
kiranmantha profile image
Kiran Mantha • Edited

Hi All, i added a new protip on how to disable backdrop click. check it out above ๐Ÿ˜„ Happy coding!!