How they made controls at Github? Modal dialog

  • Episode1: Dropdown
  • Episode2: Modal dialog
  • Episode3: Hamburger menu
  • Episode4: Popup

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>

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);
  }
}

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);
    }
  }

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);
  }
}

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.

Protip

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
  }
})

Asusual you can find the working example here.

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

26