JSFiddle - React, Tailwind, and code Playground

by Udi Talias

HTML

<header>
      <div class="glitchButton" style="float:right;"></div>
      <h1>Fancy Button Demo</h1>
    </header>
    
    <fancy-button>Hello</fancy-button>
    <fancy-button icon="/refresh.svg">refresh</fancy-button>
    
    <template>
      <style>
        :host { 
          align-items: center;
          border: 2px solid currentColor;
          border-radius: 2em;
          color: #000;
          cursor: pointer;
          display: inline-flex;
          font-family: sans-serif;
          font-size: .8em;
          height: 2.5em;
          justify-content: center;
          padding: 0 2em;
          vertical-align: middle;
        }
        :host(:hover) {
          box-shadow: 2px 2px 0 currentColor;
          text-decoration: underline;
        }
        :host(:active) {
          box-shadow: none;
          transform: translate(2px, 2px);
        }
        img {
          display: none;
          height: 1em;
          margin-right: .5em;
          width: 1em;
        }
      </style>
      <img><span><slot></slot></span>
    </template>

CSS

/* CSS files add styling rules to your content */

body {
  font-family: helvetica, arial, sans-serif;
  margin: 2em;
}

h1 {
  font-style: italic;
  color: #373fff;
}

JavaScript

// Be sure to take a look at index.html as well!
let template = document.querySelector('template');

class FancyButton extends HTMLElement {
  constructor() {
    super(); // this is mandatory
    this.setAttribute('role', 'button');
    this.setAttribute('tabindex', '0');
  }
  connectedCallback() {
    let shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.appendChild(document.importNode(template.content, true));
    this.iconEl = shadowRoot.querySelector('img');
    this.setIcon(this.getAttribute('icon'));
  }
  attributeChangedCallback(attr, oldVal, newVal) {
    if (attr === 'icon' && oldVal !== newVal) {
      this.setIcon(newVal);
    }
  }
  setIcon(url) {
    if (!this.iconEl) return;
    if (url === null) {
      this.iconEl.style.display = 'none';
    } else {
      this.iconEl.src = url;
      this.iconEl.style.display = 'block';
    }
  }
}

FancyButton.observedAttributes = ['icon'];

customElements.define('fancy-button', FancyButton);