Vue Menu Aim

1.2.0 · abandoned · verified Sun Apr 19

Vue Menu Aim is a Vue.js plugin designed to implement the 'menu-aim' functionality for improving the user experience with complex nested menus. This pattern, often popularized by Amazon, intelligently detects a user's intent to move their mouse from a parent menu item to its corresponding submenu, preventing accidental deactivation or closure of the submenu when the mouse briefly passes over other menu items. It calculates a 'forgiving triangle' area, allowing users to move diagonally without triggering hover-out events on intermediate elements. The package is currently at version 1.2.0 and has not seen updates since May 2019, making it primarily compatible with Vue 2 applications. It is particularly useful for projects requiring sophisticated dropdown or fly-out menus where standard hover delays are insufficient to provide a smooth interaction. It does not follow a regular release cadence and is no longer actively maintained.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to integrate `vue-menu-aim` as a Vue 2 plugin, initializing it within `mounted` and `updated` hooks. It shows how to pass configuration options like `rowSelector`, `top`, `left`, and `activate`/`deactivate` callbacks to manage submenu visibility based on the menu-aim logic.

import Vue from 'vue';
import vueMenuAim from 'vue-menu-aim';

Vue.use(vueMenuAim);

export default {
  data() {
    return {
      catalog: [
        { id: 1, title: 'Category 1' },
        { id: 2, title: 'Category 2' }
      ]
    };
  },
  mounted() {
    // Example of delayed initialization or for non-SSR scenarios
    this.$nextTick(() => {
      this.initializeMenuAim();
    });
  },
  updated() {
    // Re-initialize if menu structure might change, e.g., in v-for loops
    this.initializeMenuAim();
  },
  methods: {
    initializeMenuAim() {
      const menuElements = document.querySelectorAll(".menu-aim");
      if (menuElements.length === 0) return;

      // Assume an activator exists for context, e.g., a Vuetify v-menu activator
      const activator = document.querySelector(".v-menu__activator") || { offsetHeight: 0, offsetLeft: 0 };

      menuElements.forEach(menu => {
        this.vueMenuAim(menu, {
          rowSelector: ".menu-li", // Selector for individual menu items
          top: activator.offsetHeight,
          left: activator.offsetLeft,
          activate: row => {
            console.log('Activating row:', row.textContent); 
            // Logic to show a submenu for the activated row
            // e.g., add 'active' class to row, display corresponding submenu
          },
          deactivate: row => {
            console.log('Deactivating row:', row.textContent);
            // Logic to hide the submenu
          }
        });
      });
    }
  },
  template: `
    <div id="app">
      <div class="v-menu__activator" style="position: absolute; top: 10px; left: 10px; width: 50px; height: 30px; background-color: lightblue;">Menu Trigger</div>
      <v-list class="menu-aim" style="position: absolute; top: 40px; left: 10px; border: 1px solid #ccc; width: 200px;">
        <template v-for="element in catalog">
          <div :key="element.title" class="menu-li" style="padding: 8px; border-bottom: 1px solid #eee; cursor: pointer;">
            <div class="main-group-title">{{ element.title }}</div>
            <div class="submenu-content" style="position: absolute; left: 200px; top: 0; background: #f9f9f9; border: 1px solid #ddd; padding: 10px; display: none;">Submenu for {{ element.title }}</div>
          </div>
        </template>
      </v-list>
    </div>
  `
};

view raw JSON →