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));
}
});