Search code examples
javascriptaccordionweb-componentcustom-element

How to create Accordion custom element in web component


I am trying to create an Accordion using the custom element in javascript.

the below mentioned HTML as I have written in the HTML

var accordions = document.querySelectorAll(".accordion");

for (var i = 0; i < accordions.length; i++) {
  accordions[i].onclick = function () {
    this.classList.toggle('is-open');
    var content = this.nextElementSibling;
    if (content.style.maxHeight) {
      content.style.maxHeight = null;
    } else {
      content.style.maxHeight = content.scrollHeight + "px";
    }
  }
}
<div class="container">
  <button class="accordion">Accordian #1</button>
  <div class="accordion-content">
    <p> Content 1</p>
  </div>
</div>

this code how to create using the custom element?


Solution

  • If you can create a Modern Custom Element/Web Component <my-accordion> ,
    using the Browser native <details> and <summary> elements

    <style>
      summary {
        cursor: pointer;
        font-size: 1.2em;
        margin-bottom: .5em;
      }
      details[open] {
        background: lightgreen;
        padding-left: 1em;
      }
      details[open] summary {
        background: green;
        color: white;
        margin-left: -1em;
      }
    </style>
    <my-accordion>
      <details><summary>Alpha</summary>Amazing!</details>
      <details open><summary>Bravo</summary>Note the default open attribute</details>
      <details><summary>Charlie</summary><h3>Cool!</h3>hold Ctrl Key</details>
      <details><summary>Delta</summary><B>D...</B><hr>The end</details>
    </my-accordion>
    <script>
      customElements.define('my-accordion', class extends HTMLElement {
        connectedCallback() {
          this.onclick = evt => {
            [...this.children].map(detail => {
              !evt.ctrlKey && detail.toggleAttribute("open", evt.target == detail);
            });
          }
        }
      });
    </script>

    Note: There is a toggle Event you can try (with useCapture=true), but toggleAttribute will trigger that Event! Causing a nice endless loop

    Dev.to Blog Post: The Accordion Web Component