Inline spoiler test

Source: https://dev.to/ndesmic/how-to-make-a-spoiler-component-with-web-components-3hp9

by Kai Kubasta

HTML

<p>I never thought that <wc-spoiler>Rosebud is the sled 😀</wc-spoiler>.</p>

<p>I never thought that <wc-spoiler label="Citizen Kane Spoilers">Rosebud is the sled 😀</wc-spoiler>.</p>

JavaScript

class WcSpoiler extends HTMLElement {
	#isShown = false;
	bind(element) {
		this.render = this.render.bind(element);
		this.cacheDom = this.cacheDom.bind(element);
		this.attachEvents = this.attachEvents.bind(element);
	}

	connectedCallback() {
		this.render();
		this.cacheDom();
		this.attachEvents();
	}

	render() {
		this.attachShadow({ mode: "open" });
    const label = this.getAttribute("label")
      ? this.getAttribute("label")
      : "Toggle to read spoiler";
    
		this.shadowRoot.innerHTML = `
			<style>
			:host { position: relative; display: inline-block; }
			#label-button {
				width: 100%;
				height: 100%;
				position: absolute;
				top: 0px;
				left: 0px;
				background-color: black;
				border: none;
			}
			#label-button[aria-pressed="true"] {
				background-color: transparent;
			}
			#button-text, #live-area {
				clip: rect(0 0 0 0);
				height: 0px;
				width: 0px;
				padding: 0px;
				margin: 0px;
				overflow: hidden;
			}
			</style>
			<slot aria-hidden="true"></slot>
			<div id="live-area" aria-live="polite"></div>
			<button id="label-button" aria-role="switch"><div id="button-text">${label}</div></button>
			`;
	}
	cacheDom() {
		this.dom = {
			labelButton: this.shadowRoot.querySelector("#label-button"),
			buttonText: this.shadowRoot.querySelector("#button-text"),
			liveArea: this.shadowRoot.querySelector("#live-area"),
			slot: this.shadowRoot.querySelector("slot")
		};
	}
  attributeChangedCallback(name, oldValue, newValue) {
     if (oldValue !== newValue) {
      this[name] = newValue;
     }
  }
	attachEvents() {
		this.dom.labelButton.addEventListener("click", () => {
			this.#isShown = !this.#isShown;
      this.dom.slot.ariaHidden = this.#isShown ? "false" : "true";
			this.dom.labelButton.ariaPressed = this.#isShown ? "true" : "false";
			this.dom.liveArea.textContent = this.#isShown ? this.textContent : "";
		});
	}
  set label(val){
    if(this.dom?.buttonText && val.trim()){
      this.dom.buttonText = val;
    }
...