Optional Tooltip

by tnhu

HTML

<optional-tooltip class="tooltip--bottom"  data="This is a strong strong strong message">
  <strong>This is a strong</strong>
</optional-tooltip>


<optional-tooltip class="tooltip--bottom" data="This is a strong strong strong message">
  <strong style="max-width: 300px;">This is a strong</strong>
</optional-tooltip>

CSS

body {margin: 100px;}

optional-tooltip,
optional-tooltip > * {
  display: inline-block;
}

optional-tooltip > * {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

optional-tooltip:not([data-tooltip]):before,
optional-tooltip:not([data-tooltip]):after {
  display: none !important;
}


/* the :before pseudo-element contains the triangle */


/* the :after pseudo-element contains the text */

[class*=tooltip--] {
  position: relative;
}

[class*=tooltip--]:before,
[class*=tooltip--]:after {
  position: absolute;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  box-sizing: border-box;
  transition: .5s ease;
  transition-delay: 0s;
}

.tooltip--show:before,
.tooltip--show:after,
[class*=tooltip--]:hover:before,
[class*=tooltip--]:hover:after {
  visibility: visible;
  opacity: 1;
  transition-delay: .1s;
}

[class*=tooltip--]:before {
  content: '';
  position: absolute;
  background: transparent;
  height: 6px;
  width: 6px;
  border: 6px solid transparent;
}

[class*=tooltip--]:after {
  background: #383838;
  font-weight: normal;
  color: white;
  padding: 6px 8px;
  font-size: 12px;
  line-height: 1.4;
  white-space: nowrap;
  box-shadow: 1px 1px 4px 1px rgba(0, 0, 0, .2);
  border-radius: 3px;
  text-align: left;
  content: attr(data-tooltip);
}

[class*=tooltip--top]:before {
  border-top-color: #383838;
}

[class*=tooltip--bottom]:before {
  border-bottom-color: #383838;
}

.tooltip--left:before {
  border-left-color: #383838;
}

.tooltip--right:before {
  border-right-color: #383838;
}

[class*=tooltip--top]:before {
  bottom: calc(100% - 6px)
}

[class*=tooltip--top]:after {
  bottom: calc(100% + 6px)
}

.tooltip--top:before {
  left: 50%;
  margin-left: -6px;
}

.tooltip--top:after {
  left: 50%;
  transform: translateX(-50%);
}

[class*=tooltip--bottom]:before {
  top: calc(100% - 6px)
}

[class*=tooltip--bottom]:after {
  top: calc(100% + 6px)
}

.tooltip--bottom:before {
  left: calc(50% -...

JavaScript

function init() {
  try {
    function defineProperties(target, props) {
      for (var i = 0, len = props.length; i < len; i++) {
        var descriptor = props[i]
        descriptor.enumerable = descriptor.enumerable || false
        descriptor.configurable = true
        if ('value' in descriptor) descriptor.writable = true
        Object.defineProperty(target, descriptor.key, descriptor)
      }
    }

    var OptionalTooltip = (function(parent) {
      var upgrade = function() {
        return parent.apply(this, arguments) || this
      }

      function constructor() {}

      function OptionalTooltip() {
        var self = upgrade.apply(this, arguments)
        return constructor.apply(self, arguments) || self
      }

      OptionalTooltip.prototype = Object.create(parent.prototype, {
        constructor: {
          configurable: true,
          writable: true,
          value: OptionalTooltip
        }
      })

      OptionalTooltip.prototype.attributeChangedCallback = function attributeChangedCallback(
        attributeName,
        oldValue,
        newValue,
        namespace
      ) {
        var th = this

        setTimeout(function() {
          th.adjustTooltip()
        }, 250)
      }

      OptionalTooltip.prototype.adjustTooltip = function adjustTooltip() {
        var ATTR = 'data-tooltip'
        var child = this.firstElementChild

        if (child && child.scrollWidth > child.offsetWidth) {
          this.setAttribute(ATTR, this.getAttribute('data'))
        } else {
          this.removeAttribute(ATTR)
        }
      }

      defineProperties(OptionalTooltip, [
        {
          key: 'observedAttributes',
          get: function get() {
            return ['data']
          }
        }
      ])

      return OptionalTooltip
    })(HTMLElement)

    customElements.define('optional-tooltip', OptionalTooltip)
  } catch (e) {
    console.error(e)
  }
}

if (window.customElements) {
  init()
} else {
  var script =...