DEV Community

Cover image for ACME - The Accordion Web Component in 187 Bytes
Danny Engelman
Danny Engelman

Posted on • Edited on

ACME - The Accordion Web Component in 187 Bytes

TL;DR;

  • Do not unlearn HTML when you build Web Components.
  • "Design Systems" add bloated code to create an Accordion.
  • Use the default <details> and <summary> elements to built a <details-accordion> Custom Element.

If you have a hammer,

everything starts to look like a nail

Now we got this great technology Web Components, it is easy to get excited and use Custom Elements for everything in your Design System:

I won't name the Design Systems, and won't link to bloated JavaScript code.

Their HTML looks like this:

<ACME-accordion>
    <ACME-accordion-item label="..." content="Content 1" expanded></ACME-accordion-item>
    <ACME-accordion-item label="..." content="Content 2"></ACME-accordion-item>
</ACME-accordion>
Enter fullscreen mode Exit fullscreen mode

or

<ACME-accordion>
    <ACME-accordion-panel>
        <div slot="summary">...</div>
        <div>...</div>
    </ACME-accordion-panel>
    <ACME-accordion-panel>
        <div slot="summary">...</div>
        <div>...</div>
    </ACME-accordion-panel>
</ACME-accordion>
Enter fullscreen mode Exit fullscreen mode

or

<ACME-accordion>
    <h3 slot="invoker"><button>...</button></h3>
    <p slot="content">...</p>
    <h3 slot="invoker"><button>...</button></h3>
    <p slot="content">...</p>
</ACME-accordion>
Enter fullscreen mode Exit fullscreen mode

Good, old, HTML

The Open/Close functionality is available in standard HTML with the <details> and <summary> elements.

Add a 7 line vanilla Web Component:

customElements.define('details-accordion', class extends HTMLElement {
 connectedCallback() {
  this.onclick = evt => [...this.children].map(detail => {
   !evt.ctrlKey && detail.toggleAttribute("open", evt.target == detail);
  });
 }
});
Enter fullscreen mode Exit fullscreen mode

To create an Accordion:

<details-accordion>
    <details open>
        <summary>...</summary>
        ...
    </details>
    <details>
        <summary>...</summary>
        ...
    </details>
    <details>
        <summary>...</summary>
        ...
    </details>
</details-accordion>
Enter fullscreen mode Exit fullscreen mode

hold down the Ctrl key to open multiple <details>

Notes:

  • There is no shadowDOM, so easily apply any CSS styling you want
  • <details> itself also has a click handler and will open/close!
  • For every click on <details-accordion> all children are toggled;
  • using .map instead of .forEach saves 4 bytes



Top comments (0)