<div id="app">
  <div ref="container" class="container">
    <!-- Action buttons -->
    <button v-for="action in actionButtons" :key="action" @click="doAction(action)">
      {{ action }}
    </button>
    <!-- Menu button -->
    <button ref="menuButton" v-show="menuActions.length" @click.stop="toggleMenu">
      &hellip;
    </button>
    <!-- Action menu items -->
    <div ref="menu" v-show="isMenuOpen" class="menu">
      <button v-for="action in menuActions" :key="action" @click="doAction(action)">
        {{ action }}
      </button>
    </div>
  </div>

  <p>Container Size</p>
  <div class="change-size">
    <button @click="changeSize('100%')">100%</button>
    <button @click="changeSize('1400px')">1400px</button>
    <button @click="changeSize('400px')">400px</button>
    <button @click="changeSize('200px')">200px</button>
  </div>
</div>
.container {
  display: flex;
  width: 100%; /* This can be changed via the buttons. */
  padding: 8px;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #ffe2e4;

  button {
    border: 0;
    cursor: pointer;
  }

  & > button {
    margin: 0.25rem;
    padding: 12px 20px;
    font-size: 16px;
    border-radius: 0.25rem;
    background: #ed3c3c;
    color: #fff;

    &:hover {
      background: #b01a1a;
    }
    &:active {
      background: #e86f6f;
    }
  }
  .menu {
    display: flex;
    flex-direction: column;
    background: #b01a1a;
    border-radius: 8px;
    overflow: hidden;

    & > button {
      font-size: 15px;
      padding: 10px 24px;
      border-radius: 0;
      background: transparent;
      text-align: left;
      color: #fff;

      &:hover {
        background: #ed3c3c;
      }
      &:active {
        background: #e86f6f;
      }
    }
  }
}

/* The rest is just setup */

html,
body,
#app {
  height: 100%;
}

#app {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: sans-serif;
  padding: 16px;
}

p {
  margin-top: 32px;
  text-align: center;
  color: #4c11f7;
  text-transform: uppercase;
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.5px;
}

.change-size {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;

  button {
    width: 100px;
    margin: 2px;
    padding: 12px 20px;
    border: 0;
    border-radius: 4px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.5px;
    background: #4c11f7;
    color: #fff;
    cursor: pointer;

    &:hover {
      background: #3000e0;
    }
    &:active {
      background: #5c00ff;
    }
  }
}
View Compiled
let resizeObserver;
let popperInstance;

new Vue({
  el: "#app",
  data() {
    return {
      actions: ["Edit", "Save", "Copy", "Rename", "Share", "Delete"],
      isMenuOpen: false,
      menuActions: [] // Actions that should be shown in the menu
    };
  },
  computed: {
    actionButtons() {
      // Actions that should be shown as buttons outside the menu
      return this.actions.filter(
        (action) => !this.menuActions.includes(action)
      );
    }
  },
  mounted() {
    // Attach ResizeObserver to the container
    resizeObserver = new ResizeObserver(this.onResize);
    resizeObserver.observe(this.$refs.container);
    // Close the menu on any click
    document.addEventListener("click", this.closeMenu);
  },
  beforeDestroy() {
    // Clean up the observer and event listener
    resizeObserver.disconnect();
    document.removeEventListener("click", this.closeMenu);
  },
  methods: {
    onResize() {
      requestAnimationFrame(async () => {
        // Place all buttons outside the menu
        if (this.menuActions.length) {
          this.menuActions = [];
          await this.$nextTick();
        }

        const isOverflowing = () =>
          this.$refs.container.scrollWidth > this.$refs.container.offsetWidth;

        // Move buttons into the menu until the container is no longer overflowing
        while (isOverflowing() && this.actionButtons.length) {
          const lastActionButton = this.actionButtons[
            this.actionButtons.length - 1
          ];
          this.menuActions.unshift(lastActionButton);
          await this.$nextTick();
        }
      });
    },
    toggleMenu() {
      if (!this.isMenuOpen) {
        this.isMenuOpen = true;
        popperInstance = Popper.createPopper(
          this.$refs.menuButton,
          this.$refs.menu,
          {
            placement: "bottom-end",
            modifiers: [
              { name: "flip" },
              { name: "offset", options: { offset: [0, 1] } }
            ]
          }
        );
      } else this.closeMenu();
    },
    closeMenu() {
      if (!this.isMenuOpen) return;
      this.isMenuOpen = false;
      popperInstance.destroy();
      popperInstance = undefined;
    },
    doAction(action) {
      console.log(action + " clicked!");
    },
    changeSize(size) {
      this.$refs.container.style.width = size;
    }
  }
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.9.3/umd/popper.min.js