Repository: go-gitea/gitea
File: web_src/js/webcomponents/overflow-menu.ts (TypeScript)

Code before:
        this.menuItemsEl.append(item);
      } else {
        itemFlexSpace.insertAdjacentElement('beforebegin', item);
      }
    }

    // measure which items are partially outside the element and move them into the button menu
    // flex space and overflow menu are excluded from measurement
    itemFlexSpace?.style.setProperty('display', 'none', 'important');
    itemOverFlowMenuButton?.style.setProperty('display', 'none', 'important');
    this.tippyItems = [];
    const menuRight = this.offsetLeft + this.offsetWidth;
    const menuItems = this.menuItemsEl.querySelectorAll<HTMLElement>('.item, .item-flex-space');
    let afterFlexSpace = false;
    for (const item of menuItems) {
      if (item.classList.contains('item-flex-space')) {
        afterFlexSpace = true;
        continue;
      }
      if (afterFlexSpace) item.setAttribute('data-after-flex-space', 'true');
      const itemRight = item.offsetLeft + item.offsetWidth;
      if (menuRight - itemRight < 38) { // roughly the width of .overflow-menu-button with some extra space
        this.tippyItems.push(item);

        // close tippy when clicking item of tippy
        item.addEventListener('click', () => {
          this.button?._tippy.hide();
        });
      }
      // refresh overflow-button active state
      item.addEventListener('click', () => {
        this.updateButtonActivationState();
      });
    }
    itemFlexSpace?.style.removeProperty('display');
    itemOverFlowMenuButton?.style.removeProperty('display');

    // if there are no overflown items, remove any previously created button
    if (!this.tippyItems?.length) {
      const btn = this.querySelector('.overflow-menu-button');
      btn?._tippy?.destroy();
      btn?.remove();
      return;
    }

    // remove aria role from items that moved from tippy to menu
    for (const item of menuItems) {
      if (!this.tippyItems.includes(item)) {
        item.removeAttribute('role');
      }
    }

Review comment (refactor):
You are adding duplicate event handlers, each `updateItems` call adds a bunch of new handlers.

Code after:
        this.menuItemsEl.append(item);
      } else {
        itemFlexSpace.insertAdjacentElement('beforebegin', item);
      }
    }

    // measure which items are partially outside the element and move them into the button menu
    // flex space and overflow menu are excluded from measurement
    itemFlexSpace?.style.setProperty('display', 'none', 'important');
    itemOverFlowMenuButton?.style.setProperty('display', 'none', 'important');
    this.tippyItems = [];
    const menuRight = this.offsetLeft + this.offsetWidth;
    const menuItems = this.menuItemsEl.querySelectorAll<HTMLElement>('.item, .item-flex-space');
    let afterFlexSpace = false;
    for (const [idx, item] of menuItems.entries()) {
      if (item.classList.contains('item-flex-space')) {
        afterFlexSpace = true;
        continue;
      }
      if (afterFlexSpace) item.setAttribute('data-after-flex-space', 'true');
      const itemRight = item.offsetLeft + item.offsetWidth;
      if (menuRight - itemRight < 38) { // roughly the width of .overflow-menu-button with some extra space
        const onlyLastItem = idx === menuItems.length - 1 && this.tippyItems.length === 0;
        const lastItemFit = onlyLastItem && menuRight - itemRight > 0;
        const moveToPopup = !onlyLastItem || !lastItemFit;
        if (moveToPopup) this.tippyItems.push(item);
      }
    }
    itemFlexSpace?.style.removeProperty('display');
    itemOverFlowMenuButton?.style.removeProperty('display');

    // if there are no overflown items, remove any previously created button
    if (!this.tippyItems?.length) {
      const btn = this.querySelector('.overflow-menu-button');
      btn?._tippy?.destroy();
      btn?.remove();
      this.button = null;
      return;
    }

    // remove aria role from items that moved from tippy to menu
    for (const item of menuItems) {
      if (!this.tippyItems.includes(item)) {
        item.removeAttribute('role');
      }
    }

    // move all items that overflow into tippy
    for (const item of this.tippyItems) {
      item.setAttribute('role', 'menuitem');
      this.tippyContent.append(item);