JSFiddle - React, Tailwind, and code Playground

HTML

<template id="myheadingtemplate">
    <div>
      <i class="icon"></i>
      <h1>
        <content></content>
      </h1>
      <a href="#" >#</a>
    </div>
    <style>
        i.icon:before {font-size:30px;}
        i.user:before {content: '☻';}
        i.pentagon:before {content: '⬟';}
        h1 {display: inline-block;}
    </style>
  </template>

  <template id="myblocktemplate">
    <div>
      <my-heading></my-heading>
      <content></content>
    </div>
    <style>
       div {
         border: 1px solid #000;
         padding: 5%;
         margin-bottom: 5%;
       }
    </style>
  </template>

<my-block>
  <my-block heading-icon="user" heading="My important heading" >
    Lorem ipsum
  </my-block>
    
  <my-block heading-icon="pentagon" heading="My second heading" >
    Lorem ipsum
  </my-block>
</my-block>

JavaScript

function generateComponent(elementName, tagName, templateSelector, postCreateCallback) {
  var elementPrototype = Object.create(HTMLElement.prototype);
  elementPrototype.createdCallback = function() {
    var shadow = this.createShadowRoot();
    var template = document.querySelector(templateSelector);
    var clone = document.importNode(template.content, true);
    shadow.appendChild(clone);
    if (postCreateCallback) { postCreateCallback(shadow, this); }
  };
  window[elementName] = document.registerElement(tagName, {prototype: elementPrototype});
}

function slugify(slug) {
  return slug.toLowerCase().replace(/\s/g,'-');
}

generateComponent('MyBlockElement', 'my-block', '#myblocktemplate', function (shadow, scope) {
  var headingDOM = shadow.querySelector('my-heading');
  var heading = scope.getAttribute('heading');
  var icon = scope.getAttribute('heading-icon');
  if (headingDOM) {
    if (heading) {
      headingDOM.innerText = heading;
    } else {
      headingDOM.style.display = 'none';
    }
    if (icon) {
      headingDOM.setAttribute('icon', icon);
    }
  }
});

generateComponent('MyHeadingElement', 'my-heading', '#myheadingtemplate',
function (shadow, scope) {
  var icon = scope.getAttribute('icon');
  var iconDOM = shadow.querySelector('i');
  var linkDOM = shadow.querySelector('a');
  if (icon && iconDOM) {
    iconDOM.classList.add(icon);
  }
  if (linkDOM && scope.innerText !== '') {
      linkDOM.setAttribute('href', '#' + slugify(scope.innerText));
  }
});