const containers = document.querySelectorAll('.seller-list-tag-container');

containers.forEach(container => {
  // Clear container content in case of re-render
  container.innerHTML = '';

  const categories_combined = container.getAttribute('data-categories') || "";
  const categoriesArray = categories_combined.split(",").map(cat => cat.trim()).filter(cat => cat.length > 0);

  // An array to store tags for measurement purpose
  const tags = categoriesArray.map(cat => {
    const tag = document.createElement("div");
    tag.className = "seller-list-tag-tag";
    tag.textContent = cat;
    container.appendChild(tag);
    return tag;
  });

  // Create toggle button but don't add yet
  const toggleBtn = document.createElement("div");
  toggleBtn.className = "seller-list-tag-toggle";
  toggleBtn.style.cursor = "pointer";
  toggleBtn.style.userSelect = "none";
  toggleBtn.style.padding = "6px 14px";
  toggleBtn.style.borderRadius = "6px";
  toggleBtn.style.backgroundColor = "#121535";
  toggleBtn.style.color = "white";
  toggleBtn.style.fontSize = "14px";
  toggleBtn.style.whiteSpace = "nowrap";
  toggleBtn.style.transition = "background-color 0.3s";
  toggleBtn.addEventListener("mouseenter", () => {
    toggleBtn.style.backgroundColor = "#1e2759";
  });
  toggleBtn.addEventListener("mouseleave", () => {
    toggleBtn.style.backgroundColor = "#121535";
  });

  // Function to check how many tags can fit
  function updateTags() {
    const containerWidth = container.clientWidth - 10; // little margin for safety
    let usedWidth = 0;
    const toggleBtnWidth = 60; // arbitrary default, will measure dynamically later
    let lastVisibleIndex = -1;

    // Reset all tags to be visible first
    tags.forEach(t => t.style.display = "inline-flex");

    // Insert toggle button temporarily for measurement if not in DOM
    if (!container.contains(toggleBtn)) {
      container.appendChild(toggleBtn);
    }
    // Measure toggle button width with current text
    toggleBtn.style.display = 'inline-flex';
    toggleBtn.textContent = ''; // reset
    toggleBtn.textContent = '+99'; // temp large to get accurate width
    const measuredToggleBtnWidth = toggleBtn.offsetWidth;

    // Hide toggle button initially, we'll add it only if needed
    toggleBtn.style.display = 'none';

    // Calculate how many tags fit, taking toggle button width into account
    for (let i = 0; i < tags.length; i++) {
      const tagWidth = tags[i].offsetWidth + 8; // include gap between tags (using 8px from CSS gap property)
      if (usedWidth + tagWidth <= containerWidth) {
        usedWidth += tagWidth;
        lastVisibleIndex = i;
      } else {
        break;
      }
    }

    // If all fit, no toggle needed
    if (lastVisibleIndex === tags.length - 1) {
      // show all tags, hide toggle button
      tags.forEach(t => t.style.display = "inline-flex");
      toggleBtn.style.display = 'none';
      toggleBtn.removeEventListener('click', onToggleClick);
      toggleBtn.dataset.open = 'false';
      return;
    }

    // Otherwise, reserve space for toggle button
    usedWidth = 0;
    lastVisibleIndex = -1;
    for (let i = 0; i < tags.length; i++) {
      const tagWidth = tags[i].offsetWidth + 8;
      if (usedWidth + tagWidth + measuredToggleBtnWidth <= containerWidth) {
        usedWidth += tagWidth;
        lastVisibleIndex = i;
      } else {
        break;
      }
    }

    // Show visible tags, hide others
    tags.forEach((t, idx) => {
      if (idx <= lastVisibleIndex) {
        t.style.display = "inline-flex";
      } else {
        t.style.display = "none";
      }
    });

    const hiddenCount = tags.length - lastVisibleIndex - 1;
    toggleBtn.textContent = `+${hiddenCount}`;
    toggleBtn.style.display = 'inline-flex';
    toggleBtn.dataset.open = 'false';

    // Add toggle button at the end (if not already)
    if (!container.contains(toggleBtn)) {
      container.appendChild(toggleBtn);
    }
  }

  function onToggleClick() {
    const isOpen = toggleBtn.dataset.open === 'true';
    if (isOpen) {
      // Collapse
      toggleBtn.dataset.open = 'false';
      updateTags();
    } else {
      // Expand all
      tags.forEach(t => t.style.display = "inline-flex");
      toggleBtn.dataset.open = 'true';
      toggleBtn.textContent = '−'; // minus sign
    }
  }

  toggleBtn.addEventListener('click', onToggleClick);

  // On window resize recalc tags fitting
  window.addEventListener('resize', () => {
    if (toggleBtn.dataset.open !== 'true') {
      updateTags();
    }
  });

  updateTags();
});

.seller-list-tag-container {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 0px 10px 0px 0px;
    max-width: 100%; /* 最大寬度，避免太撐 */
    margin: -10px auto;
  }

  /* Tag基礎造型 */
  .seller-list-tag-tag {
    background-color: #121535;
    color: white;
    border-radius: 6px;
    padding: 6px 14px;
    font-size: 14px;
    white-space: nowrap;
    user-select: none;
    cursor: default;
    transition: background-color 0.3s;
  }
  .seller-list-tag-tag:hover {
    background-color: #1e2759;
  }

  /* 響應式調整字體大小與間距 */
  @media (max-width: 1024px) {
    .seller-list-tag-container {
      max-width: 90vw;
    }
    .seller-list-tag-tag {
      font-size: 13px;
      padding: 5px 12px;
    }
  }

  @media (max-width: 600px) {
    .seller-list-tag-tag {
      font-size: 12px;
      padding: 4px 10px;
    }
  }

.seller-list-tag-toggle {
  background-color: #121535;
  color: white;
  border-radius: 6px;
  padding: 6px 14px;
  font-size: 14px;
  white-space: nowrap;
  user-select: none;
  cursor: pointer;
  transition: background-color 0.3s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 4px;
}
.seller-list-tag-toggle:hover {
  background-color: #1e2759;
}

The above codes will used to display the categories of the seller in the online shop. When tags display exceed the width of container, the remaining tags will collapsed and the + button will appear for user to click to see more tags. There are problems when display more than on seller on the page together, and the tags except the first seller will all collapsed by default. Please help me to fix it