tailwind dropdown menus

by Imri Paloja

HTML

<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">
<link
  rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.3.1/css/all.min.css">
  

<button
  data-dropdown-id="action-menu"
  class="dropdown-button cursor-pointer hover:text-dark-900 relative flex h-11 w-11 items-center justify-center rounded border border-gray-800 bg-eb-dark text-eb-dark transition-colors hover:text-eb-gray-100 hover:text-eb-gray-700 hover:text-gray-700"
>
  <i class="fa-solid fa-ellipsis-vertical"></i>
</button>

<div
  data-id="action-menu"
  data-conflicts="notification-window"
  data-effect-on="animate__fadeInUp"
  data-effect-off="animate__fadeOutDown"
  class="animate__animated absolute z-80 animate__faster animate__fadeOutDown hidden bg-eb-dark border max-w-25 border-gray-800 backdrop-blur-sm shadow-md rounded text-gray-800"
>
  <ul
    class="px-2 pb-2 text-sm text-body font-medium"
    aria-labelledby="dropdownInformationButton">
    <li>
      <a
        href="/admin/settings"
        class="inline-flex items-center w-full p-2 hover:bg-neutral-tertiary-medium text-gray-800 hover:text-eb-red transition duration-300 rounded"
      >
        <i class="fa-solid fa-info"></i></i> &nbsp; Info
      </a>
    </li>
    <li>
      <a
        href="/admin/settings"
        class="inline-flex items-center w-full p-2 hover:bg-neutral-tertiary-medium text-gray-800 hover:text-eb-red transition duration-300 rounded"
      >
       <i class="fa-solid fa-trash"></i> &nbsp; Trash
      </a>
    </li>
    <li>
      <a
        href="/admin/settings"
        class="inline-flex items-center w-full p-2 hover:bg-neutral-tertiary-medium text-gray-800 hover:text-eb-red transition duration-300 rounded"
      >
        <i class="fa-solid fa-xmark"></i> &nbsp; Delete
      </a>
    </li>
 ...

CSS

@theme {
  --color-eb-red: #e60000;
  --color-eb-dark: #1b1e1f;
  --color-eb-gray: #181a1b;

  --font-sans: 'Inter', sans-serif;
}

/* Optional: Additional custom utilities */
@layer utilities {
  /*.text-gradient {*/
  /*    background-clip: text;*/
  /*    -webkit-background-clip: text;*/
  /*    color: transparent;*/
  /*}*/
}

JavaScript

/**
 * Manage drop down menus
 */
function dropdown_menus() {
  // ///// ///// ///// ///// /////
  // data-dropdown-id="notification-items" class="dropdown-button"
  //const dropdown_buttons = document.querySelectorAll('.dropdown-button');

  const dropdown_buttons = document.querySelectorAll(
    '.dropdown-button:not(.processed)',
  );

  // label

  dropdown_buttons.forEach((dropdown_button) => {
    // dropdown-button

    dropdown_button.classList.add('processed');

    // If someone clicks a button
    dropdown_button.addEventListener('click', () => {
      const dropdownId = dropdown_button.getAttribute('data-dropdown-id');
      // user-menu
      // notification-menu

      if (!dropdownId) {
        console.warn(
          'Dropdown button is missing data-dropdown-id:',
          dropdown_button,
        );
        return;
      }

      const menu = document.querySelector('[data-id="' + dropdownId + '"]');

      if (!menu) {
        console.warn(`No menu found with data-id="${dropdownId}"`);
        return;
      }

      const conflicts = document.querySelector(
        '[data-id="' + menu.getAttribute('data-conflicts') + '"]',
      );

      const effects_on = menu.getAttribute('data-effect-on');
      const effects_off = menu.getAttribute('data-effect-off');

      if (menu) {
        if (conflicts) {
          //conflicts.classList.add('hidden');
          conflicts.classList.remove(effects_on);
          conflicts.classList.add(effects_off);
        }

        if (menu.classList.contains(effects_on)) {
          menu.classList.remove('hidden');
          menu.classList.add(effects_off);
          menu.classList.remove(effects_on);
        } else {
          menu.classList.remove('hidden');
          menu.classList.add(effects_on);
          menu.classList.remove(effects_off);
        }
      }
    });
  });
}

if (document.readyState === 'loading') {
 ...