Harris Schneiderman edited this page Sep 7, 2017 · 4 revisions

Modals

What is needed?

Modals consist of two things: the modal trigger and the modal dialog.

Modal Trigger

The modal trigger should always be a button element. It requires a data-dialog-id attribute which should be the id of the modal that it triggers. For example, a modal with id="my-modal" should have a trigger with data-dialog-id="my-modal"

The modal dialog

The modal dialog should consist of the following:

  • the "dqpl-modal" class
  • role="dialog"
  • and id for the trigger to point at in it's data-dialog-id attribute
  • Within the <div class="dqpl-modal" role="dialog"></div> element:
    • An element with the "dqpl-dialog-inner" class
    • Within "dqpl-dialog-inner":
      • An element with the "dqpl-modal-header" which consists of the modal's heading and the close button
        • The close button should be a <button /> element with the "dqpl-modal-close" class
    • A sibling of "dqpl-modal-header" should be an element with the "dqpl-modal-content". This is where all of the modal's content will live.
    • A sibling of the "dqpl-modal-content" element, should be the modal's footer (an element with the class "dqpl-modal-footer").

API

The custom events "dqpl:dialog:aria-hide" and "dqpl:dialog:aria-show"are available to be trigged on modal elements. "dqpl:dialog:aria-hide" will apply aria-hidden="true" to every thing except the modal (and parents of the modal), while "dqpl:dialog:aria-show" will revert the aria-hidden="true".

In addition, adding the "data-force-action="true" attribute will prevent the dqpl javascript from allowing the modal to be closed via escape keydown.

Also, adding the "data-no-resize="true" attribute will prevent the dqpl javascript from responsively resizing the modal content's height.

const modal = document.querySelector('.dqpl-modal');
const e = new CustomEvent('dqpl:dialog:aria-hidden', {
  bubbles: true,
  cancelable: false
});

modal.dispatchEvent(e);

Example HTML

Simple modal with just text

The main thing to note here, is that the footer just consists of a single "OK" button.

<button class="dqpl-button-secondary" type="button" data-dialog-id="demo-1">Modal with just text</button>
<div class="dqpl-modal" role="dialog" id="demo-1">
  <div class="dqpl-dialog-inner">
    <div class="dqpl-modal-header">
      <h2>Text modal</h2>
      <button class="dqpl-modal-close dqpl-icon" type="button">
        <div class="fa fa-close" aria-hidden="true"></div>
        <div class="dqpl-offscreen">Close</div>
      </button>
    </div>
    <div class="dqpl-modal-content">
      <p>This is a modal with just text in it and stuff.</p>
    </div>
    <div class="dqpl-modal-footer">
      <button class="dqpl-button-secondary dqpl-modal-cancel" type="button">OK</button>
    </div>
  </div>
</div>

Complex modal with a form

The main thing to note here, is that the footer consists of both a "SAVE" and a "CANCEL" button.

<button class="dqpl-button-secondary" type="button" data-dialog-id="demo-2">Modal with form</button>
<div class="dqpl-modal" role="dialog" id="demo-2">
  <div class="dqpl-dialog-inner">
    <div class="dqpl-modal-header">
      <h2>Modal with form</h2>
      <button class="dqpl-modal-close" type="button">
        <div class="fa fa-close" aria-hidden="true"></div>
        <div class="dqpl-offscreen">Close</div>
      </button>
    </div>
    <div class="dqpl-modal-content">
      <div class="field-section" role="group" aria-labelledby="personal-info">
        <h3 id="personal-info">Personal information</h3>
        <div class="dqpl-field-wrap">
          <label class="dqpl-label dqpl-required" for="first-name">First name</label>
          <input class="dqpl-text-input" type="text" id="first-name" aria-required="true"/>
          <div class="dqpl-error-wrap"></div>
        </div>
        <div class="dqpl-field-wrap">
          <label class="dqpl-label dqpl-required" for="last-name">Last name</label>
          <input class="dqpl-text-input" type="text" id="last-name" aria-required="true"/>
          <div class="dqpl-error-wrap"></div>
        </div>
      </div>
      <div class="field-section" role="group" aria-labelledby="contact-info">
        <h3 id="contact-info">Contact information</h3>
        <div class="dqpl-field-wrap">
          <label class="dqpl-label dqpl-required" for="email">Email</label>
          <input class="dqpl-text-input" type="text" id="email" aria-required="true"/>
          <div class="dqpl-error-wrap"></div>
        </div>
        <div class="dqpl-field-wrap">
          <label class="dqpl-label dqpl-required" for="phone">Phone number</label>
          <input class="dqpl-text-input" type="text" id="phone" aria-required="true"/>
          <div class="dqpl-error-wrap"></div>
        </div>
      </div>
    </div>
    <div class="dqpl-modal-footer">
      <button class="dqpl-button-primary" type="button">Save</button>
      <button class="dqpl-button-secondary dqpl-modal-cancel" type="button">Cancel</button>
    </div>
  </div>
</div>
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.