Tailwind CSS Dropdown with details-menu Web Component
Tags: tailwindcss, webcomponents
Published: 2021-03-21 16:00:24

---
title: Tailwind CSS Dropdown with details-menu Web Component
published: true
date: 2021-03-21 09:00:00 UTC
tags: #tailwindcss #webcomponents
canonical_url: https://stefanzweifel.dev/posts/2021/03/21/tailwind-css-dropdown-with-details-menu-web-component
---

If you didn't know yet, GitHub maintains a growing list of open sourced [Web Components](https://github.com/github/github-elements).

One is love to use is [details-menu-element](https://github.com/github/details-menu-element). It adds a `<details-menu>` element which can be used in combination with `<details>` and `<summary>` to create dropdowns. The best thing: You don't have to write any additional JavaScript to make it work. Everything is bundled inside `<details-menu>`.

I use this in websites where I don't want to include a heavy JavaScript framework like Vue.js or React, but still need an accessible dropdown.

In [this example](https://codepen.io/stefanzweifel/pen/JjbgrNN?editors=1000) on CodePen, I've adapted the [Tailwind UI dropdown example](https://tailwindui.com/components/application-ui/elements/dropdowns#component-f8a14da22f26a67757b19f2fe3ca00ed) to use `<detail-menu>`.

I've also sprinkled in some [Alpine.js](https://github.com/alpinejs/alpine) to close the dropdown if the user clicks anywhere outside of it.

## Source Code[#](#source-code "Permalink")

The HTML without any Tailwind CSS classes or Alpine.js attributes looks like this.

```
<details open>
  <summary>
    <div>
        Options
        <!-- Heroicon name: solid/chevron-down -->
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
            <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
        </svg>
    </div>
  </summary>
  <details-menu role="menu">
    <div role="none">
      <a href="#" role="menuitem">Account settings</a>
      <a href="#" role="menuitem">Support</a>
      <a href="#" role="menuitem">License</a>
      <form method="POST" action="#" role="none">
        <button type="submit" role="menuitem">
          Sign out
        </button>
      </form>
    </div>
  </details-menu>
</details>

```

Next I've added the Alpine.js attributes. We init Alpine.js on the `<details>`-element and give it a `$ref`. We then listen to the `@click.away` event and remove the `open` attribute, to close/hide the dropdown.

```
<details
  x-data 
  x-ref="dropdown" 
  @click.away="$refs.dropdown.removeAttribute('open');" 
  open
  >
  <summary>
    <div>
        Options
        <!-- Heroicon name: solid/chevron-down -->
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
            <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
        </svg>
    </div>
  </summary>
  <details-menu role="menu">
    <div role="none">
      <a href="#" role="menuitem">Account settings</a>
      <a href="#" role="menuitem">Support</a>
      <a href="#" role="menuitem">License</a>
      <form method="POST" action="#" role="none">
        <button type="submit" role="menuitem">
          Sign out
        </button>
      </form>
    </div>
  </details-menu>
</details>

```

And here is the final component with its Tailwind CSS classes added.

```
<!-- https://tailwindui.com/components/application-ui/elements/dropdowns#component-f8a14da22f26a67757b19f2fe3ca00ed -->

<details open x-data x-ref="dropdown" @click.away="$refs.dropdown.removeAttribute('open');" class="relative inline-block text-left">

  <summary>
    <div class="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500">
      Options
      <!-- Heroicon name: solid/chevron-down -->
      <svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
        <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
      </svg>
    </div>
  </summary>

  <details-menu role="menu" class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">

    <div class="py-1" role="none">
      <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" role="menuitem">Account settings</a>
      <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" role="menuitem">Support</a>
      <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" role="menuitem">License</a>
      <form method="POST" action="#" role="none">
        <button type="submit" class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900" role="menuitem">
          Sign out
        </button>
      </form>
    </div>
  </details-menu>
</details>

```

On the JavaScript side, you only have to import two libraries to make everything work.

- `import '@github/details-menu-element'`
- `import 'alpinejs'`

## Outro[#](#outro "Permalink")

Web Components haven't catched on in mainstream web development – or at least not in my bubble – but I see much potential in them.

Especially components like `<details-menu>` which are "headless" and don't come with any styles attached to them, have a bright future a head of them.  
The team at Tailwind Labs for example is already working on [Headless UI](https://headlessui.dev). A set of UI components which are accessible and unstyled and can be used in React or Vue.

I have the felling that the growing popularity of utility CSS frameworks will spill over to Web Components and we see Web Components used more in mainstream web development projects.

* * *

As mentioned in the beginning, GitHub open sourced quite a few Web Components they use on github.com. Here's a quick list of components I started using in some of my projects.

- [github/clipboard-copy-element](https://github.com/github/clipboard-copy-element)
- [github/tab-container-element](https://github.com/github/tab-container-element)
- [github/auto-complete-element](https://github.com/github/auto-complete-element)
- [github/details-dialog-element](https://github.com/github/details-dialog-element)
- [github/time-elements](https://github.com/github/time-elements)

Check them out. Maybe you can replace an existing component in your projects with them and reduce the size of your bundles.