JSFiddle - React, Tailwind, and code Playground
by graphettion
HTML
<button-wc variant="contained">Click Me</button-wc>
<text-field-wc label="Name"></text-field-wc>
<checkbox-wc label="Agree"></checkbox-wc>
<button onclick="toggleTheme()">Toggle Theme</button>
<script>
function toggleTheme() {
document.body.dataset.theme = document.body.dataset.theme === 'dark' ? 'light' : 'dark';
}
</script>
JavaScript
// Button Component
class ButtonWC extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.render();
}
static get observedAttributes() {
return ['variant'];
}
attributeChangedCallback() {
this.render();
}
render() {
const variant = this.getAttribute('variant') || 'text';
this.shadowRoot.innerHTML = `
<style>
button {
padding: 6px 16px;
border-radius: 4px;
font-size: 14px;
text-transform: uppercase;
cursor: pointer;
transition: background-color 0.2s, box-shadow 0.2s;
}
button[variant="contained"] {
background-color: var(--primary);
color: #fff;
border: none;
}
button[variant="outlined"] {
background: transparent;
border: 1px solid var(--primary);
color: var(--primary);
}
button[variant="text"] {
background: transparent;
border: none;
color: var(--primary);
}
button:hover {
filter: brightness(90%);
}
button:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.5);
}
</style>
<button variant="${variant}">
<slot></slot>
</button>
`;
}
}
customElements.define('button-wc', ButtonWC);
// TextField Component
class TextFieldWC extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.render();
}
static get observedAttributes() {
return ['label'];
}
attributeChangedCallback() {
this.render();
}
render() {
const label = this.getAttribute('label') || '';
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
position: relative;
margin: 16px 0;
}
label {
position: absolute;
top: 8px;
left: 12px;
...