<button onclick="openDialog('dialog1', this, 'close')" id="dialog-label">
    Open Dialog
</button>
<div role="dialog" id="dialog1" aria-labelledby="dialog1_label" aria-modal="true" class="lightbox-overlay">
    <button class="lightbox-overlay__close" id="close">
        <div class="visually-hidden">Close dialog</div>
    </button>
    <div>The content of the overlay goes here</div>
</div>

No notes defined.

/* No context defined. */
  • Content:
    const attemptFocus = element => {
      try {
        element.focus();
      } catch (e) {
        console.log(e);
      }
    
      return document.activeElement === element;
    };
    
    export class Dialog {
      constructor({ dialogId, focusAfterClosed, focusFirst, closeCallBack }) {
        this.dialogNode = document.getElementById(dialogId);
        this.closeCallBack = closeCallBack;
        this.dialogId = dialogId;
    
        if (this.dialogNode === null) {
          throw new Error(`No element found with id="${dialogId}".`);
        }
    
        const validRoles = ['dialog', 'alertdialog'];
        const isDialog = (this.dialogNode.getAttribute('role') || '')
          .trim()
          .split(/\s+/g)
          .some(token => validRoles.some(role => token === role));
    
        if (!isDialog) {
          throw new Error(
            'Dialog() requires a DOM element with ARIA role of dialog or alertdialog.'
          );
        }
    
        if (typeof focusAfterClosed === 'string') {
          this.focusAfterClosed = document.getElementById(focusAfterClosed);
        } else if (typeof focusAfterClosed === 'object') {
          this.focusAfterClosed = focusAfterClosed;
        } else {
          throw new Error(
            'the focusAfterClosed parameter is required for the aria.Dialog constructor.'
          );
        }
    
        this.dialogNode.classList.add('lightbox-overlay--active');
        document.body.style.overflow = 'hidden';
    
        if (typeof focusFirst === 'string') {
          this.focusFirst = document.getElementById(focusFirst);
        } else if (typeof focusFirst === 'object') {
          this.focusFirst = focusFirst;
        } else {
          this.focusFirst = null;
        }
    
        if (this.focusFirst) {
          this.focusFirst.focus();
        }
    
        this.lastFocus = document.activeElement;
        this.addEventListeners();
      }
    
      focusFirstDescendant(element) {
        for (let i = 0; i < element.childNodes.length; i++) {
          const child = element.childNodes[i];
    
          if (attemptFocus(child) || this.focusFirstDescendant(child)) {
            return true;
          }
        }
        return false;
      }
    
      trapFocus(event) {
        if (this.dialogNode.contains(event.target)) {
          this.lastFocus = event.target;
        } else {
          this.focusFirstDescendant(this.dialogNode);
          this.lastFocus = document.activeElement;
        }
      }
    
      destroy() {
        const videoDialog = document.querySelector('#generated-video-dialog');
        const vimeoDialog = document.querySelector('#generated-vimeo-video-dialog');
    
        // added conditon to fix  search popup close event trigger while video lighbox close
        if (
          this.dialogId === 'efl-search-mechanic-dialog' &&
          ((videoDialog &&
            videoDialog.classList.contains('lightbox-overlay--active')) ||
            (vimeoDialog &&
              vimeoDialog.classList.contains('lightbox-overlay--active')))
        ) {
          return;
        }
    
        this.removeListeners();
        this.dialogNode.classList.remove('lightbox-overlay--active');
        document.body.style.overflow = 'initial';
        this.focusAfterClosed.focus();
    
        if (this.closeCallBack) {
          this.closeCallBack();
        }
      }
    
      // EVENT LISTENERS
      handleEscape(event) {
        if (event.key !== 'Escape') {
          return;
        }
        this.destroy();
      }
    
      handleClick({ target }) {
        // We are only interested in clicks on the outer dialog, or the close button
        if (
          !target.classList.contains('lightbox-overlay__close') &&
          target.getAttribute('role') !== 'dialog'
        ) {
          return;
        }
    
        this.destroy();
      }
    
      removeListeners() {
        document.removeEventListener('focus', this.trapFocus, true);
        document.removeEventListener('keydown', this.handleEscape, true);
        document.removeEventListener('click', this.handleClick, true);
      }
    
      addEventListeners() {
        document.addEventListener('click', event => this.handleClick(event));
        document.addEventListener('keydown', event => this.handleEscape(event));
        document.addEventListener('focus', event => this.trapFocus(event));
      }
    }
    
    export default () => {
      window.openDialog = (
        dialogId,
        focusAfterClosed,
        focusFirst,
        closeCallBack
      ) => {
        return new Dialog({
          dialogId,
          focusAfterClosed,
          focusFirst,
          closeCallBack,
        });
      };
    };
    
  • URL: /components/raw/lightbox-overlay/lightbox-overlay.js
  • Filesystem Path: src/library/components/lightbox-overlay/lightbox-overlay.js
  • Size: 4.1 KB
  • Content:
    .lightbox-overlay {
      align-items: center;
      background-color: rgba($black, 0.8);
      bottom: 0;
      display: none;
      justify-content: center;
      left: 0;
      position: fixed;
      right: 0;
      top: 0;
      z-index: 200;
    
      &--active {
        display: flex;
      }
    
      &__close {
        align-items: center;
        background: none;
        border: 0;
        border-radius: 50%;
        display: inline-block;
        height: 3.8rem;
        justify-content: center;
        width: 3.8rem;
        position: absolute;
        top: -4.5rem;
        right: -7px;
        z-index: 1;
        cursor: pointer;
        outline: none;
    
        &::before {
          content: '';
          background: url('./assets/images/lightbox-close.svg') no-repeat center
            center;
          background-size: contain;
          width: 3.4rem;
          height: 3.4rem;
          display: inline-block;
          position: relative;
          left: -10px;
        }
        &:hover {
          &::before {
            background: url('./assets/images/lightbox-close-blue.svg') no-repeat
              center center;
            background-size: contain;
            width: 3.4rem;
            height: 3.4rem;
          }
        }
      }
      .video {
        position: relative;
        width: calc(100%);
    
        &--is-playing {
          width: 100%;
          .lightbox-overlay__close {
            display: none;
          }
        }
    
        &__poster {
          &::before {
            content: '';
            background: linear-gradient(
              180deg,
              rgba(var(--brand-primary-rgb), 0) 0%,
              rgba(var(--brand-primary-rgb), 1) 100%
            );
            border-radius: 4px 4px 0 0;
            transform: rotate(180deg);
            height: 153px;
            width: 100%;
            display: block;
            position: absolute;
          }
          .play-button {
            position: absolute;
            left: calc(50% - 36px);
            top: calc(50% - 36px);
            font-size: 0;
            cursor: pointer;
            &::before {
              content: '';
              background: url('./assets/images/play-button.svg') no-repeat center
                center;
              width: 71px;
              height: 71px;
              display: inline-block;
            }
          }
        }
        &__player-wrap iframe {
          width: 100%;
          height: 56.25vw;
        }
    
        &__player-wrap .vimeo-video-player {
          width: 100%;
          height: 100%;
        }
    
        &__player-wrap img {
          object-fit: cover;
          width: 100%;
          height: 100%;
          display: none;
        }
    
        @media screen and (max-width: $mq-medium) and (orientation: landscape) {
          &__player-wrap iframe {
            height: 34rem;
          }
        }
    
        @media screen and (min-width: $mq-medium) {
          min-width: 576px;
          width: 50vw;
          height: 28.15vw;
          min-height: 32.4rem;
          &--is-playing {
            width: 80rem;
          }
          &__player-wrap {
            width: 100%;
            height: 100%;
          }
          &__player-wrap iframe {
            width: 100%;
            height: 100%;
          }
        }
    
        @media screen and (min-width: $mq-large) {
          max-width: 128rem;
        }
      }
    }
    
  • URL: /components/raw/lightbox-overlay/lightbox-overlay.scss
  • Filesystem Path: src/library/components/lightbox-overlay/lightbox-overlay.scss
  • Size: 2.9 KB
<button onclick="openDialog('dialog1', this, 'close')" id="dialog-label">
  Open Dialog
</button>
<div role="dialog" id="dialog1" aria-labelledby="dialog1_label" aria-modal="true" class="lightbox-overlay">
  <button class="lightbox-overlay__close" id="close">
    <div class="visually-hidden">Close dialog</div>
  </button>
  <div>The content of the overlay goes here</div>
</div>
  • Handle: @lightbox-overlay
  • Preview:
  • Filesystem Path: src/library/components/lightbox-overlay/lightbox-overlay.hbs