JSFiddle - React, Tailwind, and code Playground
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>event test</title>
</head>
<body>
<h1>event test</h1>
<side-nav>
<nav-item id="1">1</nav-item>
<nav-item id="2">2</nav-item>
<nav-item id="3">3</nav-item>
<nav-item id="4">4</nav-item>
</side-nav>
</body>
</html>
JavaScript
const sideNavTemplate = document.createElement("template");
sideNavTemplate.innerHTML = `
<style>
:host {
display: block;
}
:host([hidden]) {
display: none
}
.root {
display: flex;
justify-content: space-between;
}
</style>
<div class="root"><slot>Item Display</slot></div>`;
class SideNav extends HTMLElement {
constructor()
{
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(sideNavTemplate.content.cloneNode(true));
}
async connectedCallback() {
this.addEventListener('navitem-selected', (event) => {
let items = this.shadowRoot.querySelector('slot').assignedElements();
console.log(event, items);
items.forEach((item) => {
if(item.getAttribute('id') !== event.detail.id) {
item.removeAttribute('selected');
}
});
});
}
}
window.customElements.define('side-nav', SideNav);
const navItemTemplate = document.createElement("template");
navItemTemplate.innerHTML = `
<style>
:host {
display: block;
}
:host([hidden]) {
display: none
}
.root {
display: flex;
justify-content: space-between;
padding: 16px;
}
.root:hover{
background-color: aliceblue;
}
.selected{
background-color: teal;
color: white;
}
</style>
<div class="root"><slot>Item Display</slot></div>`;
class NavItem extends HTMLElement {
id;
constructor()
{
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(navItemTemplate.content.cloneNode(true));
}
static get observedAttributes() {
return ['id', 'selected'];
}
attributeChangedCallback(name, oldValue, newValue) {
if(name == 'id'){
this.id = newValue;
}
if(name == 'selected')
{
if(newValue){
this.shadowRoot.querySelector('.root').classList.add('selected');
} else {
...