<div id="overlay-45948-98488" class="overlay" aria-labelledby="overlay-45948-98488-headline" data-destroy-after-close="true" data-redirect-after-close="false">
    <div class="overlay__backdrop"></div>

    <div class="overlay__overlay u-inverted" role="document">
        <div class="overlay__bar">

            <button class="overlay__close" type="button" title="Schließen">
                <svg class="icon icon--cross" viewBox="0 0 200 200" aria-hidden="true">
                    <use xlink:href="/assets/icons/icons.3bafb6df0d.svg#cross"></use>
                </svg> </button>
        </div>

        <div class="overlay__content">
            <div class="overlay__headline">
                <h2 id="overlay-45948-98488-headline" class="headline headline--2"><span class="headline__text">Im CV empfehlen sich folgende Angaben zu Sprachkenntnissen:</span></h2>
            </div>

            <div class="overlay__blocks">
                <div class="overlay__block">

                    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est
                    <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est

                </div>
            </div>
        </div>

    </div>
</div>
{% set open = open ?? false %}
{% set closeUrl = closeUrl ?? false %}
{% set destroyAfterClose = destroyAfterClose ?? true %}
{% set redirectAfterClose = redirectAfterClose ?? false %}
{% set footer = block('footer') is defined ? block('footer')|trim : null %}
{% set label = label ?? false %}
{% set id = id ??? html_id('overlay') -%}
{% set labelledby = not label ? (labelledby ??? ('headline' | namespaceInputId(id))) %}

<div {{ html_attributes({
  id: id,
  class: {
    'overlay': true,
    'overlay--slim': slim ?? false,
    'overlay--centered': centered ?? false,
    'overlay--with-footer': footer ?? false,
  } | merge(classes ?? {}),
  hidden: not open,
  aria: {
    label: label,
    labelledby: labelledby,
  },
  data: {
    'destroy-after-close': destroyAfterClose ? 'true' : 'false',
    'redirect-after-close': redirectAfterClose ? 'true' : 'false',
  },
}, componentAttrs ?? {}, attrs ?? {}) }}>
  <div class="overlay__backdrop"></div>

  <div class="overlay__overlay u-inverted" role="document">
    <div class="overlay__bar">
      {% set buttonTag = closeUrl ? 'a' : 'button' %}

      <{{ buttonTag }} {{ html_attributes({
        class: 'overlay__close',
        type: not closeUrl ? 'button',
        href: closeUrl,
        title: 'Close' | t('site'),
      }) }}>
        {% include '@icon' with { icon: 'cross' } only %}
      </{{ buttonTag }}>
    </div>

    <div class="overlay__content">
      {% if block('content') is defined %}
        {{ block('content') }}
      {% else %}
        {% if headline|default %}
          <div class="overlay__headline">
            {% include '@headline' with {
              level: 2,
            } | merge(headline) | merge({
              size: 2,
              id: 'headline' | namespaceInputId(id),
            }) only %}
          </div>
        {% endif %}

        <div class="overlay__blocks">
          {% if use|default %}
            <div class="overlay__block">
              {% include use with configuration | merge({
                id: 'content' | namespaceInputId(id),
              }) only %}
            </div>
          {% else %}
            {% for block in blocks|default([]) %}
              <div {{ html_attributes({
                id: block.id ?? false,
                class: {
                  'overlay__block': true,
                  'overlay__block--media': block.type|default in ['image', 'video', 'quote', 'buttons'],
                },
              }, block.attributes ?? {}) }}>
                {{ block.content | raw }}
              </div>
            {% endfor %}
          {% endif %}
        </div>
      {% endif %}
    </div>

    {% if footer %}
      <div class="overlay__footer">
        {{ block('footer') }}
      </div>
    {% endif %}
  </div>
</div>
{
  "open": true,
  "headline": {
    "text": "Im CV empfehlen sich folgende Angaben zu Sprachkenntnissen:"
  },
  "blocks": [
    {
      "content": "!twig\n\n<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est\n<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est\n"
    }
  ]
}
  • Content:
    :root {
      --overlay-background-color: var(--color-midnight);
      --overlay-color: var(--color-white);
      --overlay-close-color: var(--color-orange);
      --overlay-close-hover-color: var(--color-midnight);
      --overlay-backdrop-opacity: 0.58;
      --overlay-max-width: 75rem;
      --overlay-slim-max-width: 50rem;
      --overlay-animation: slide-from-right;
      --overlay-block-spacing: 2rem;
    
      @include use-responsive-sizing(--overlay-bar-height, responsive-map(xs 6rem, xl 9rem));
      @include use-responsive-sizing(--overlay-footer-height, responsive-map(xs 6rem, xl 9rem));
      @include use-responsive-sizing(--overlay-content-padding-inline, responsive-map(xs 3rem, xl 6rem));
      @include use-responsive-sizing(--overlay-content-padding-block, responsive-map(xs 3rem, xl 6rem));
      @include use-responsive-sizing(--overlay-slim-content-padding-inline, responsive-map(xs 2rem, xl 4rem));
      @include use-responsive-sizing(--overlay-centered-content-padding-inline, responsive-map(xs 2rem, xl 3rem));
      @include use-responsive-sizing(--overlay-block-spacing-media, responsive-map(xs 3.6rem, xl 5.6rem));
    }
    
    .overlay {
      animation: opacity var(--duration-default);
      inset: 0;
      position: fixed;
      z-index: z-index('overlay');
    
      &:is([hidden]) {
        display: none;
      }
    }
    
    .overlay--slim {
      --overlay-max-width: var(--overlay-slim-max-width);
      --overlay-content-padding-inline: var(--overlay-slim-content-padding-inline);
    }
    
    .overlay--centered {
      --overlay-inset: 50% 50% auto;
      --overlay-translate: -50% -50%;
      --overlay-content-padding-inline: var(--overlay-centered-content-padding-inline);
    }
    
    .overlay__backdrop {
      background-color: var(--overlay-background-color);
      inset: 0;
      opacity: var(--overlay-backdrop-opacity);
      position: absolute;
      z-index: 1;
    }
    
    .overlay__overlay {
      animation: opacity var(--duration-default), var(--overlay-animation) var(--duration-long);
      background-color: var(--overlay-background-color);
      color: var(--overlay-color);
      inline-size: var(--overlay-width, 100%);
      inset: var(--overlay-inset, 0 0 0 auto);
      max-inline-size: var(--overlay-max-width);
      overflow-x: hidden;
      overflow-y: auto;
      overscroll-behavior: contain;
      position: absolute;
      translate: var(--overlay-translate, none);
      z-index: 2;
    }
    
    .overlay__bar {
      --overlay-bar-height-unit: calc(var(--overlay-bar-height) / 6);
    
      align-items: center;
      backdrop-filter: blur(10px);
      block-size: var(--overlay-bar-height);
      display: flex;
      inline-size: 100%;
      inset: 0 0 auto auto;
      justify-content: flex-end;
      max-inline-size: var(--overlay-max-width);
      padding-inline: calc(var(--overlay-content-padding-inline) - var(--overlay-bar-height-unit));
      position: fixed;
      z-index: 2;
    }
    
    .overlay__close {
      align-items: center;
      block-size: calc(var(--overlay-bar-height-unit) * 4);
      color: var(--overlay-close-color);
      cursor: pointer;
      display: flex;
      font-size: calc(var(--overlay-bar-height-unit) * 2);
      inline-size: calc(var(--overlay-bar-height-unit) * 4);
      justify-content: center;
      line-height: 1;
      text-align: start;
      transition-property: background-color, color, opacity;
      user-select: none;
    
      &:is(:hover:not([disabled]), :focus:not(.has-invisible-focus)) {
        background-color: var(--overlay-close-color);
        color: var(--overlay-close-hover-color);
      }
    
      &[disabled] {
        cursor: not-allowed;
        opacity: 0.5;
      }
    }
    
    .overlay__content {
      --overlay-inner-padding-block: 2rem;
      --social-media-links-text-align: left;
      --social-media-links-links-align: flex-start;
    
      display: flex;
      flex-direction: column;
      min-block-size: 100%;
      padding-block: var(--overlay-bar-height) var(--overlay-footer-height);
      padding-inline: var(--overlay-content-padding-inline);
    
      .overlay:not(.overlay--with-footer) & {
        --overlay-footer-height: var(--overlay-content-padding-block);
      }
    }
    
    .overlay__blocks {
      line-height: var(--line-height-body);
      margin-block-start: 4rem;
    }
    
    .overlay__block {
      margin-block-end: var(--overlay-block-spacing);
    
      .overlay__blocks:first-child &:first-child,
      .overlay__blocks:first-child &:first-child > *:first-child {
        margin-block-start: 0;
      }
    
      .overlay__blocks:last-child &:last-child {
        margin-block-end: 0;
      }
    
      > * + * {
        margin-block-start: var(--overlay-block-spacing);
      }
    
      > .headline {
        margin-block-start: calc(var(--overlay-block-spacing) * 2);
      }
    }
    
    .overlay__block--media {
      margin-block: var(--overlay-block-spacing-media);
    }
    
    .overlay__footer {
      --icon-button-background-color: transparent;
      --icon-button-background-color-active: transparent;
      --icon-button-border-color: transparent;
      --icon-button-border-color-active: transparent;
      --icon-button-icon-color: var(--color-orange);
      --icon-button-icon-color-active: var(--color-orange);
      --icon-button-size: 2.6rem;
      --icon-button-icon-size: 2.6rem;
      --icon-button-gap: 0.6rem;
      --icon-button-underline-height: 1px;
      --icon-button-text-size: 1.6rem;
    
      align-items: center;
      background-color: var(--overlay-background-color);
      block-size: var(--overlay-footer-height);
      display: flex;
      gap: 4rem;
      inline-size: 100%;
      inset: auto 0 0 auto;
      max-inline-size: var(--overlay-max-width);
      padding-inline: var(--overlay-content-padding-inline);
      position: fixed;
      z-index: 2;
    
      > :not(:first-child)::before {
        background-color: var(--color-midnight-offset);
        content: '';
        inline-size: 0.2rem;
        inset-block: 20%;
        margin-inline-start: -1.9rem;
        position: absolute;
      }
    }
    
  • URL: /components/raw/overlay/overlay.scss
  • Filesystem Path: src/components/3-organisms/overlay/overlay.scss
  • Size: 5.4 KB
  • Content:
    import { createFocusTrap, FocusTrap } from 'focus-trap';
    import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
    import { on } from 'delegated-events';
    import invisibleFocus from '../../../javascripts/utils/invisibleFocus';
    import moveFocus from '../../../javascripts/utils/moveFocus';
    import tobii from '../../../javascripts/globals/lightbox';
    
    const dialogs = new Map<HTMLElement, FocusTrap>();
    
    const createOverlay = (
      $overlay: HTMLElement,
      destroyAfterClose = true,
      redirectAfterClose = false,
    ): FocusTrap => {
      const existingOverlay = dialogs.get($overlay);
    
      if (existingOverlay) {
        return existingOverlay;
      }
    
      const previouslyFocused = document.activeElement;
      const dialog = createFocusTrap($overlay, {
        initialFocus: false,
        returnFocusOnDeactivate: false,
        allowOutsideClick(event) {
          // Allow always clicks to cookie consent banner, which has always a higher z-index
          if (event.target instanceof HTMLElement && event.target.closest('.ccm-root')) {
            return true;
          }
    
          return false;
        },
        onPostActivate() {
          // Send event
          $overlay.dispatchEvent(new Event('overlay:show', { bubbles: true }));
    
          // Scroll lock on overlay scroll container
          const $overlayScroll = $overlay.querySelector('.overlay__overlay');
          if ($overlayScroll) {
            disableBodyScroll($overlayScroll);
          }
    
          // Move focus
          moveFocus($overlay);
        },
        onDeactivate() {
          // Hide overlay
          $overlay.hidden = true;
    
          // Remove scroll lock
          const $overlayScroll = $overlay.querySelector('.overlay__overlay');
          if ($overlayScroll) {
            enableBodyScroll($overlayScroll);
          }
    
          // Make focus on source element invisible
          if (previouslyFocused instanceof HTMLElement) {
            if (document.contains(previouslyFocused)) {
              invisibleFocus(previouslyFocused);
            } else if (previouslyFocused.id) {
              const $replaced = document.getElementById(previouslyFocused.id);
    
              if ($replaced) {
                invisibleFocus($replaced);
              }
            }
          }
    
          // Set close url as new page URL
          const $closeLink =
            $overlay.querySelector<HTMLAnchorElement>('a.overlay__close');
    
          if ($closeLink) {
            window.history.replaceState(null, '', $closeLink.href);
          }
    
          // Send event
          $overlay.dispatchEvent(new Event('overlay:hide', { bubbles: true }));
    
          // Redirect after close
          if (redirectAfterClose && $closeLink) {
            document.location = $closeLink.href;
          }
        },
        onPostDeactivate() {
          // Destroy dialog!
          if (destroyAfterClose) {
            $overlay.dispatchEvent(new Event('overlay:destroy', { bubbles: true }));
            $overlay.remove();
            dialogs.delete($overlay);
          }
        },
      });
    
    
      // Save dialog for later
      dialogs.set($overlay, dialog);
    
      $overlay.addEventListener('overlay:scroll-to-top', () => {
        $overlay.querySelector('.overlay__overlay')?.scrollTo({ top: 0 });
      });
    
      $overlay.dispatchEvent(new Event('overlay:init', { bubbles: true }));
    
      if (!$overlay.hidden) {
        dialog.activate();
      }
    
      return dialog;
    };
    
    export const createOverlays = ($container: HTMLElement | Document) => {
      $container.querySelectorAll<HTMLElement>('.overlay').forEach(($overlay) => {
        createOverlay(
          $overlay,
          $overlay.getAttribute('data-destroy-after-close') === 'true',
          $overlay.getAttribute('data-redirect-after-close') === 'true',
        );
      });
    };
    
    createOverlays(document);
    
    on('click', '.overlay__close, .overlay__backdrop', (event) => {
      const { currentTarget: $close } = event;
    
      event.preventDefault();
    
      const $overlay = $close.closest<HTMLElement>('.overlay');
    
      if ($overlay) {
        const existingOverlay = dialogs.get($overlay);
        existingOverlay?.deactivate();
      }
    });
    
    on('click', '[data-overlay]', (event) => {
      const { currentTarget: $trigger } = event;
    
      const $overlay = document.getElementById($trigger.dataset.overlay ?? '');
    
      if ($overlay) {
        event.preventDefault();
        $overlay.hidden = false;
        createOverlay($overlay, false).activate();
      }
    });
    
    tobii.on('open', () => {
      dialogs.forEach((focusTrap) => {
        focusTrap.pause();
      });
    });
    
    tobii.on('close', () => {
      dialogs.forEach((focusTrap) => {
        focusTrap.unpause();
      });
    });
    
    export default createOverlay;
    
  • URL: /components/raw/overlay/overlay.ts
  • Filesystem Path: src/components/3-organisms/overlay/overlay.ts
  • Size: 4.4 KB

No notes defined.