Dropdown

dropdown.astro

---
// https://www.w3schools.com/howto/howto_js_dropdown.asp
import type { HTMLAttributes } from "astro/types";
import "./dropdown.css";

interface Props extends HTMLAttributes<"div"> {}
const { class: className, ...props } = Astro.props;
---

<div class:list={["dropdown", className]} {...props}>
  <button class="dropdown-btn">
    <slot name="button">Dropdown</slot>
  </button>
  <div class="dropdown-content">
    <slot name="content">
      <a>Link 1</a>
      <a>Link 2</a>
      <a>Link 3</a>
    </slot>
  </div>
</div>

<script>
  function init() {
    const dropdowns = document.querySelectorAll(".dropdown");

    for (const dropdown of dropdowns) {
      const button = dropdown.querySelector(".dropdown-btn");
      const content = dropdown.querySelector(".dropdown-content");
      if (!button || !content) continue;

      button.addEventListener("click", () => {
        content.classList.toggle("show");
      });

      document.addEventListener("click", (event) => {
        const target = event.target as HTMLElement;
        if (!dropdown.contains(target)) {
          content.classList.remove("show");
        }
      });
    }
  }

  document.addEventListener("DOMContentLoaded", init);
  document.addEventListener("astro:after-swap", init);
</script>

dropdown.css

/* Dropdown Button */
.dropdown-btn {
  background-color: var(--bg-color, #7a7a7a);
  color: var(--color, #fff);
  padding: 0.8em;
  border: none;
  cursor: pointer;
  border-radius: var(--border-radius, 0.2em);
}

/* Dropdown button on hover & focus */
.dropdown-btn:hover,
.dropdown-btn:focus {
  background-color: var(--bg-color, #505050);
}

/* The container <div> - needed to position the dropdown content */
.dropdown {
  position: relative;
  display: inline-block;
}

/* Dropdown Content (Hidden by Default) */
.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 10em;
  box-shadow: 0px 0.5em 1em 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
  border-radius: var(--border-radius, 0.25em);
  overflow: hidden;
}

/* Links inside the dropdown */
.dropdown-content a {
  color: black;
  padding: 1em 1.5em;
  text-decoration: none;
  display: block;
}

/* Change color of dropdown links on hover */
.dropdown-content a:hover {
  background-color: #ddd;
}

/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.dropdown-content.show {
  display: block;
}