Skip to content

Info Tooltip13.10.5

The Info Tooltip component displays tip or information on click


$ npm i @if-design-system/info-tooltip@13.10.5

For now, the Info Tooltip is a blue copy of the Help Tooltip component. The only difference is the icon.

Edit this section

Implementation

<button class="if info-tooltip-button" type="button" aria-label="More information"></button>
<div
  class="if info-tooltip-popover [is-open]"
  aria-hidden="false"
  aria-labelledby="<title-identifier>"
  aria-describedby="<text-identifier>"
  role="dialog"
>
  <button class="if close" type="button" aria-label="Close"></button>
  [<span class="if title" id="<title-identifier>">Title</span>]
  <span class="if text" id="<text-identifier>">Text</span>
</div>

Example webcomponent implementation

class IDSInfoTooltip extends HTMLElement {
  constructor() {
    super();

    const UUID =
      '_' +
      Math.random()
        .toString(36)
        .substr(2, 9);

    const _title_content = this.getAttribute('data-title');
    const _text_content = this.getAttribute('data-text');

    const _is_standalone = this.getAttribute('data-standalone');

    const _medium_mq = window.matchMedia('screen and (min-width: 400px)');
    let _is_medium_mq = true;

    const _handleMedium = mql => {
      if (mql.matches) {
        _is_medium_mq = true;
      } else {
        _is_medium_mq = false;
      }
    };

    _medium_mq.addListener(_handleMedium);

    _handleMedium(_medium_mq);

    const _shadow_root = this.attachShadow({ mode: 'open' });
    const _button_el = document.createElement('button');

    _button_el.classList.add('if');
    _button_el.classList.add('info-tooltip-button');
    _button_el.classList.add('webcomponent');
    _button_el.setAttribute('type', 'button');
    _button_el.setAttribute('aria-label', 'More information');

    if (_is_standalone && _is_standalone !== null) {
      _button_el.classList.add('is-standalone');
    }

    const _createPopover = ({ title, text, size }) => {
      const _popover_el = document.createElement('div');
      const _close_el = document.createElement('button');
      const _text_el = document.createElement('span');

      _popover_el.classList.add('if');
      _popover_el.classList.add('info-tooltip-popover');
      _popover_el.classList.add('webcomponent');

      if (size && size !== '' && size === 'bottom') {
        _popover_el.classList.add(size);
      }

      _popover_el.setAttribute('aria-hidden', true);
      _popover_el.setAttribute('aria-labelledby', `popover-title-${UUID}`);
      _popover_el.setAttribute('aria-describedby', `popover-text-${UUID}`);
      _popover_el.setAttribute('role', 'dialog');

      _close_el.classList.add('if');
      _close_el.classList.add('close');
      _close_el.setAttribute('type', 'button');
      _close_el.setAttribute('aria-label', 'Close');

      _close_el.addEventListener('click', () => {
        _closePopover(_popover_el);
      });

      _text_el.classList.add('if');
      _text_el.classList.add('text');
      _text_el.setAttribute('id', `popover-text-${UUID}`);

      const _text = document.createTextNode(text);

      _text_el.appendChild(_text);
      _popover_el.appendChild(_close_el);

      if (title && title !== '') {
        const _title_el = document.createElement('span');
        _title_el.classList.add('if');
        _title_el.classList.add('title');
        _title_el.setAttribute('id', `popover-title-${UUID}`);
        const titleText = document.createTextNode(title);
        _title_el.appendChild(titleText);
        _popover_el.appendChild(_title_el);
      }
      _popover_el.appendChild(_text_el);

      return _popover_el;
    };

    const _popover_el = _createPopover({
      title: _title_content,
      text: _text_content
    });
    const _setPosition = () => {
      const _button_rect = _button_el.getBoundingClientRect();
      const _popover_rect = _popover_el.getBoundingClientRect();
      const _arrow_left_if_popover_overflow = _button_el.offsetLeft + _button_rect.width / 2 - 12;

      const VH = window.innerHeight;
      if (!_is_medium_mq) {
        const _mobile_popover_rect = _popover_el.getBoundingClientRect();

        _popover_el.style.left = `${_popover_el.getBoundingClientRect().left - _popover_el.offsetLeft - 24}px`;

        if (VH / 2 - _mobile_popover_rect.height < _button_rect.top) {
          _popover_el.style.top = `${_button_el.offsetTop - _mobile_popover_rect.height - _button_rect.height}px`;
          _popover_el.classList.remove('bottom');
        } else {
          _popover_el.style.top = `${_button_rect.height + 24}px`;
          _popover_el.classList.add('bottom');
        }

        _popover_el.style.setProperty('--ids-popover-arrow-vertical-position', `${_button_el.offsetTop}px`);
        _popover_el.style.setProperty(
          '--ids-popover-arrow-horizontal-position',
          `${_arrow_left_if_popover_overflow < 0 ? 0 : _arrow_left_if_popover_overflow}px`
        );
      } else {
        _popover_el.style.setProperty('--ids-popover-arrow-vertical-position', 'calc(50% - 12px)');
        _popover_el.style.setProperty('--ids-popover-arrow-horizontal-position', 'calc(50% - 12px)');
        _popover_el.style.left = _button_el.offsetLeft + _button_rect.width / 2 - _popover_rect.width / 2 + 'px';

        if (_popover_el.getBoundingClientRect().left < 24) {
          _popover_el.style.left = '0px';
          _popover_el.style.setProperty('--ids-popover-arrow-vertical-position', `${_button_el.offsetTop}px`);
          _popover_el.style.setProperty(
            '--ids-popover-arrow-horizontal-position',
            `${_arrow_left_if_popover_overflow < 0 ? 0 : _arrow_left_if_popover_overflow}px`
          );
        }

        if (VH / 2 - _popover_el.getBoundingClientRect().height < _button_rect.top) {
          _popover_el.style.top = `${_button_el.offsetTop -
            _popover_el.getBoundingClientRect().height -
            _button_rect.height}px`;
          _popover_el.classList.remove('bottom');
        } else {
          _popover_el.style.top = `${_button_rect.height + 24}px`;
          _popover_el.classList.add('bottom');
        }
      }
    };

    const _toggleAriaHidden = () => {
      _popover_el.setAttribute('aria-hidden', _popover_el.getAttribute('aria-hidden') != 'true' ? 'true' : 'false');
    };

    // Create some CSS to apply to the shadow dom
    const _style = document.createElement('style');

    _style.textContent = `<styles>`;

    const _dispatchEvent = (id, isOpen) => {
      const _event = new CustomEvent('ids:send:info-tooltip', {
        bubbles: !0,
        detail: {
          source: 'IDS_HELP_TOOLTIP',
          type: isOpen ? 'HELP_TOOLTIP_OPENED' : 'HELP_TOOLTIP_CLOSED',
          payload: {
            id: id
          }
        }
      });
      document.dispatchEvent(_event);
    };

    const _handleClickOutside = e => {
      if (!this.contains(e.target)) {
        _closePopover();
      }
    };

    const _handleKeyEsc = e => {
      if (e.key && e.key === 'Escape') {
        _closePopover();
        _button_el.focus();
      }
    };

    const _closePopover = () => {
      _popover_el.classList.remove('is-open');
      _popover_el.style.visibility = 'hidden';
      _toggleAriaHidden();

      _dispatchEvent(UUID, false);
      document.removeEventListener('keyup', _handleKeyEsc);
      document.removeEventListener('click', _handleClickOutside);
    };

    const _openPopover = () => {
      _popover_el.classList.add('is-open');
      _setPosition();

      _popover_el.style.visibility = 'visible';
      _toggleAriaHidden();
      _dispatchEvent(UUID, true);
      document.removeEventListener('keyup', _handleKeyEsc);
      document.removeEventListener('click', _handleClickOutside);
      document.addEventListener('click', _handleClickOutside);
      document.addEventListener('keyup', _handleKeyEsc);
    };

    const _togglePopover = () => {
      const _is_open = _popover_el.classList.contains('is-open');
      if (_is_open) {
        _closePopover();
      } else {
        _openPopover();
      }
    };

    let _touched = false;
    let _touch_ended = true;

    _button_el.addEventListener('touchstart', e => {
      _touch_ended = false;

      e.preventDefault();

      _openPopover();

      setTimeout(function() {
        if (!_touch_ended) {
          _touched = true;
        }
      }, 300);
    });

    _button_el.addEventListener('touchend', () => {
      if (_touched) {
        _touched = false;
        _closePopover();
        _touch_ended = true;
      }
    });
    _button_el.addEventListener('click', () => {
      if (_touched) return;
      _togglePopover();
    });

    window.addEventListener('resize', () => {
      window.requestAnimationFrame(function() {
        _setPosition();
      });
    });

    // Attach the created els to the shadow dom
    _shadow_root.appendChild(_style);
    _shadow_root.appendChild(_button_el);
    _shadow_root.appendChild(_popover_el);
    _popover_el.style.visibility = 'hidden';
  }
}

// Define the new el
customElements.define('ids-info-tooltip', IDSInfoTooltip);
Edit this section

Contact us