JSFiddle - React, Tailwind, and code Playground

HTML

<todo-list></todo-list>

JavaScript

/**
 * Base class for todo elements containing shared functionality
 * between both the <todo-list> and <todo-task> elements.
 */
class TodoElement extends HTMLElement {

  /**
   * Generates an HTML string representation of the current
   * element's HTML tag.
   * @param closed - When true generates a closing tag.
   */
  tag(closed = false) {
    const name = this.tagName.toLowerCase()
    return `&lt;${closed ? "/" : ""}${name}${closed ? "" : this.attrs()}&gt;`
  }

  /**
   * Provides the attributes string included in tag()-generated
   * tag HTML. This will be empty by default. Individual
   * components can define their own values by overridding
   * this method.
   */
  attrs() {
    return ""
  }

  /**
   * Adds styles and sets up listeners for add buttons. Add buttons
   * exist both in the todo-list and individual todo-task elements.
   */
  setupAdd() {
    const addBtn = this.shadowRoot.getElementById("add-btn")
    addBtn.addEventListener("click", () => this.onAddClick())
    const style = document.createElement("style")
    
    // Using a ::before pseudo element for the add button text
    // keeps it from being copied when the user selects all the
    // text in the component.
    style.textContent = `
    #add-btn::before{content:"+";color:green;}
    #add-btn{opacity:0.333;}
    #add-btn:hover,#add-btn:focus{opacity:1;}
    `
    this.shadowRoot.appendChild(style)
  }

  /**
   * Add button click handler. When clicked, add buttons generate an
   * event handled by todo-list.
   */
  onAddClick() {
    this.dispatchEvent(new Event("todo-add", {
      bubbles: true
    }))
  }
}

/**
 * Component definition for <todo-list> elements. A todo-list can
 * contain any number of <todo-task> elements that together make up
 * a todo list.
 */
customElements.define("todo-list", class extends TodoElement {

  /**
   * Constructor called when creating new <todo-list> elements.
   */
  constructor() {
    super()
    const shadow = this.attachShadow({ mode:...