<button class="tooltip js-tooltip" title="Begriffserklärung ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor.">Button</button>
//- Render tooltip
#{tag || 'button'}.tooltip.js-tooltip(title=tooltip)&attributes(attr) #{text}
{
  "text": "Button",
  "tooltip": "Begriffserklärung ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor."
}
  • Content:
    import { createPopper } from '@popperjs/core';
    import h from 'hyperscript';
    import randomId from '../../../javascripts/utils/random-id';
    import icon from '../../../javascripts/utils/icon';
    
    export default class Tooltip {
      constructor($el, $tooltip) {
        this.$el = $el;
        this.$tooltip = $tooltip;
    
        this.popper = null;
        this.config = {
          closeButtonClass: 'button.tooltip__close',
          openOnHover: true,
          closeOnFocusOut: true,
          placement: this.$el.dataset.placement || 'left',
          orientations: [
            'right',
            'right-start',
            'bottom',
            'left',
            'left-start',
            'top',
          ],
        };
        this.$close = $tooltip.querySelector(this.config.closeButtonClass);
    
        // Bind events
        if (this.config.openOnHover) {
          this.onMouseenterBinded = this.onMouseenter.bind(this);
          this.onMouseleaveBinded = this.onMouseleave.bind(this);
        }
        this.onClickBinded = this.onClick.bind(this);
        this.onOutsideClickBinded = this.onOutsideClick.bind(this);
        this.onTooltipFocusoutBinded = this.onTooltipFocusout.bind(this);
        this.onCloseClickBinded = this.onCloseClick.bind(this);
    
        this.$el.addEventListener('mouseenter', this.onMouseenterBinded);
        this.$el.addEventListener('click', this.onClickBinded);
        this.$close.addEventListener('click', this.onCloseClickBinded);
    
        // Initialize popper
        this.popper = createPopper(
          this.$el,
          this.$tooltip,
          {
            placement: this.config.placement,
            modifiers: [
              {
                name: 'flip',
                options: {
                  fallbackPlacements: this.config.orientations,
                },
              },
              {
                name: 'arrow',
                options: {
                  element: this.$tooltip.querySelector('.tooltip__arrow'),
                },
              },
              {
                name: 'offset',
                options: {
                  offset: [0, 8],
                },
              },
              {
                name: 'preventOverflow',
                options: {
                  padding: 5,
                },
              },
            ],
          },
        );
      }
    
      onMouseenter() {
        this.$el.addEventListener('mouseleave', this.onMouseleaveBinded);
        this.show();
      }
    
      onMouseleave() {
        this.$el.removeEventListener('mouseleave', this.onMouseleaveBinded);
        this.hide();
      }
    
      onClick(event) {
        event.preventDefault();
    
        if (this.config.openOnHover) {
          this.$el.removeEventListener('mouseleave', this.onMouseleaveBinded);
          this.$el.removeEventListener('mouseenter', this.onMouseenterBinded);
        }
        this.$close.hidden = false;
        this.show();
    
        document.addEventListener('click', this.onOutsideClickBinded);
    
        if (this.config.closeOnFocusOut) {
          this.$tooltip.addEventListener('focusout', this.onTooltipFocusoutBinded);
        }
    
        if (this.config.onClick) {
          this.config.onClick();
        }
      }
    
      onOutsideClick(event) {
        const $target = event.target;
    
        if (this.isInside($target)) {
          return;
        }
    
        this.hideAfterClick();
      }
    
      onTooltipFocusout(event) {
        const $target = event.relatedTarget;
    
        if (this.isInside($target)) {
          return;
        }
    
        this.hideAfterClick();
      }
    
      onCloseClick() {
        this.hideAfterClick();
        this.$el.focus();
      }
    
      show() {
        this.$tooltip.setAttribute('aria-hidden', 'false');
        this.popper.update();
      }
    
      hide() {
        this.$tooltip.setAttribute('aria-hidden', 'true');
        this.$el.focus();
      }
    
      hideAfterClick() {
        this.hide();
        this.$close.hidden = true;
    
        document.removeEventListener('click', this.onOutsideClickBinded);
        this.$tooltip.removeEventListener('focusout', this.onTooltipFocusoutBinded);
    
        if (this.config.openOnHover) {
          this.$el.addEventListener('mouseenter', this.onMouseenterBinded);
        }
      }
    
      isInside($target) {
        return (
          this.$tooltip.contains($target)
          || this.$tooltip === $target
          || this.$el.contains($target)
          || this.$el === $target
        );
      }
    }
    
    export const attachTooltip = ($el) => {
      const text = $el.getAttribute('title');
      const id = `tooltip-${randomId()}`;
    
      if (!text) {
        return null;
      }
    
      $el.removeAttribute('title');
    
      if (!$el.hasAttribute('aria-label')) {
        $el.setAttribute('aria-label', 'Begriffserklärung anzeigen');
      }
    
      // Templates
      const $text = h('p.tooltip__text', { attrs: { tabindex: '0' } }, text);
      const $arrow = h('.tooltip__arrow', { attrs: { 'x-arrow': '' } });
    
      const $close = h(
        'button.tooltip__close',
        {
          type: 'button',
          title: 'Schließen',
          hidden: true,
        },
        icon({
          icon: 'close',
        }),
      );
    
      const $tooltip = h(
        `.tooltip__popup#${id}`,
        {
          attrs: {
            'aria-hidden': 'true',
          },
        },
        $text,
        $arrow,
        $close,
      );
    
      $el.parentNode.insertBefore($tooltip, $el.nextSibling);
    
      return new Tooltip($el, $tooltip, {
        onClick: () => {
          $text.focus();
        },
      });
    };
    
    document
      .querySelectorAll('.js-tooltip')
      .forEach(attachTooltip);
    
  • URL: /components/raw/tooltip/tooltip.js
  • Filesystem Path: src/components/atoms/tooltip/tooltip.js
  • Size: 5 KB
  • Content:
    .tooltip {
      display: inline-block;
    
      .preview-frame & {
        margin-top: 10rem;
      }
    }
    
    .tooltip__popup {
      background-color: #000;
      box-shadow: 1px -1px 5px 0 rgba(0, 0, 0, 0.7);
      color: #fff;
      font-size: 1.4rem;
      margin: 0.2rem 0.8rem;
      max-width: 26rem;
      padding: 1.4rem 1.6rem;
      z-index: z('tooltip');
    
      &[aria-hidden='true'] {
        display: none;
      }
    
      &[aria-hidden='false'] {
        display: block;
      }
    
      .tooltip__text {
        margin-bottom: 0;
      }
    
      @include mq($until: m) {
        padding-right: 2.4rem;
      }
    }
    
    .tooltip__arrow {
      border-style: solid;
      border-width: 0.8rem;
      display: block;
      height: 0;
      position: absolute;
      width: 0;
    
      .tooltip__popup[data-popper-placement='top'] &,
      .tooltip__popup[data-popper-placement='top-end'] & {
        border-bottom: 0;
        border-left-color: transparent;
        border-right-color: transparent;
        border-top-color: #000;
        bottom: -0.8rem;
      }
    
      .tooltip__popup[data-popper-placement='right'] &,
      .tooltip__popup[data-popper-placement='right-end'] & {
        border-bottom-color: transparent;
        border-left: 0;
        border-right-color: #000;
        border-top-color: transparent;
        left: -0.8rem;
      }
    
      .tooltip__popup[data-popper-placement='bottom'] &,
      .tooltip__popup[data-popper-placement='bottom-end'] & {
        border-bottom-color: #000;
        border-left-color: transparent;
        border-right-color: transparent;
        border-top: 0;
        top: -0.8rem;
      }
    
      .tooltip__popup[data-popper-placement='left'] &,
      .tooltip__popup[data-popper-placement='left-start'] &,
      .tooltip__popup[data-popper-placement='left-end'] & {
        border-bottom-color: transparent;
        border-left-color: #000;
        border-right: 0;
        border-top-color: transparent;
        right: -0.8rem;
      }
    }
    
    .tooltip__text {
      line-height: 1.4;
    }
    
    .tooltip__close {
      cursor: pointer;
      height: 2.4rem;
      padding: 0;
      position: absolute;
      right: 0;
      top: 0;
      width: 2.4rem;
    }
    
  • URL: /components/raw/tooltip/tooltip.scss
  • Filesystem Path: src/components/atoms/tooltip/tooltip.scss
  • Size: 1.9 KB

There are no notes for this item.