CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-imengyu--vue3-context-menu

A comprehensive context menu component library for Vue 3 applications with themes, keyboard navigation, and programmatic control

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Vue3 Context Menu

Vue3 Context Menu is a comprehensive context menu component library for Vue 3 applications that enables developers to create customizable right-click menus with rich functionality. It offers both functional and component-based APIs for displaying context menus, supports nested submenus and separators, provides multiple built-in themes with both light and dark variants, and includes keyboard navigation support.

Package Information

  • Package Name: @imengyu/vue3-context-menu
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @imengyu/vue3-context-menu

Core Imports

import ContextMenu from '@imengyu/vue3-context-menu';
import '@imengyu/vue3-context-menu/lib/vue3-context-menu.css';

// For functional API
import ContextMenu from '@imengyu/vue3-context-menu';

// For component imports
import { 
  ContextMenu as ContextMenuComponent, 
  ContextMenuItem, 
  ContextMenuSeparator, 
  ContextMenuGroup,
  MenuBar 
} from '@imengyu/vue3-context-menu';

For CommonJS:

const ContextMenu = require('@imengyu/vue3-context-menu');
require('@imengyu/vue3-context-menu/lib/vue3-context-menu.css');

Basic Usage

Installation and Setup

import { createApp } from 'vue';
import ContextMenu from '@imengyu/vue3-context-menu';
import '@imengyu/vue3-context-menu/lib/vue3-context-menu.css';

const app = createApp(App);
app.use(ContextMenu);

Quick Example - Functional API

import ContextMenu from '@imengyu/vue3-context-menu';

function onContextMenu(e: MouseEvent) {
  e.preventDefault();
  
  ContextMenu.showContextMenu({
    x: e.x,
    y: e.y,
    items: [
      { 
        label: "Copy", 
        icon: "copy-icon",
        onClick: () => console.log("Copy clicked")
      },
      { 
        label: "Edit", 
        children: [
          { label: "Cut", onClick: () => console.log("Cut clicked") },
          { label: "Paste", onClick: () => console.log("Paste clicked") },
        ]
      },
      { divided: true, label: "Delete", onClick: () => console.log("Delete clicked") }
    ]
  });
}

Quick Example - Component API

<template>
  <div @contextmenu="onRightClick">
    <context-menu v-model:show="show" :options="menuOptions">
      <context-menu-item label="Copy" icon="copy-icon" @click="handleCopy" />
      <context-menu-separator />
      <context-menu-group label="Edit">
        <context-menu-item label="Cut" @click="handleCut" />
        <context-menu-item label="Paste" @click="handlePaste" />
      </context-menu-group>
    </context-menu>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const show = ref(false);
const menuOptions = ref({
  x: 0,
  y: 0,
  zIndex: 1000
});

function onRightClick(e) {
  e.preventDefault();
  menuOptions.value.x = e.x;
  menuOptions.value.y = e.y;
  show.value = true;
}
</script>

Architecture

Vue3 Context Menu is built around several key components:

  • Functional API: Global methods for programmatic menu display (showContextMenu, closeContextMenu)
  • Component API: Vue components for declarative menu construction (ContextMenu, ContextMenuItem, etc.)
  • Theme System: Built-in themes (default, flat, win10, mac) with light/dark variants
  • Position System: Automatic position adjustment to prevent menu overflow
  • Keyboard Navigation: Full keyboard control support matching Windows menu behavior
  • Menu Bar: Traditional horizontal menu bar component for desktop-style applications

Capabilities

Functional API

Core programmatic interface for displaying context menus with full configuration control. Perfect for dynamic menus and event-driven scenarios.

interface ContextMenuGlobal {
  showContextMenu(options: MenuOptions, customSlots?: Record<string, Slot>): ContextMenuInstance;
  closeContextMenu(): void;
  isAnyContextMenuOpen(): boolean;
  transformMenuPosition(element: HTMLElement, x: number, y: number, container?: HTMLElement): { x: number, y: number };
}

interface MenuOptions {
  /** Menu items array */
  items?: MenuItem[];
  /** Menu display X position */
  x: number;
  /** Menu display Y position */
  y: number;
  /** X-coordinate offset of submenu and parent menu */
  xOffset?: number;
  /** Y-coordinate offset of submenu and parent menu */
  yOffset?: number;
  /** Theme name (default, flat, win10, mac, with optional 'dark' suffix) */
  theme?: string;
  /** Menu pop-up direction relative to coordinates */
  direction?: MenuPopDirection;
  /** Z-index for menu display */
  zIndex?: number;
  /** Menu zoom level */
  zoom?: number;
  /** Custom CSS class for menu */
  customClass?: string;
  /** Enable mouse scroll wheel in menu area */
  mouseScroll?: boolean;
  /** Provide space placeholder for up/down buttons */
  updownButtonSpaceholder?: boolean;
  /** Element class name to ignore clicks */
  ignoreClickClassName?: string;
  /** Close menu when clicking outside */
  clickCloseOnOutside?: boolean;
  /** Element class name that closes menu when clicked */
  clickCloseClassName?: string;
  /** Custom icon library font class name */
  iconFontClass?: string;
  /** Vue Transition props for menu show/hide */
  menuTransitionProps?: TransitionProps;
  /** Reserve fixed-width icon area for items without icon */
  preserveIconWidth?: boolean;
  /** Enable keyboard control */
  keyboardControl?: boolean;
  /** Maximum width of menu (pixels) */
  maxWidth?: number;
  /** Maximum height of menu (pixels) */
  maxHeight?: number;
  /** Minimum width of menu (pixels) */
  minWidth?: number;
  /** Close when user scrolls */
  closeWhenScroll?: boolean;
  /** Padding for submenu position adjustment */
  adjustPadding?: { x: number, y: number } | number;
  /** Automatically adjust position to prevent overflow */
  adjustPosition?: boolean;
  /** Container element for menu mounting */
  getContainer?: HTMLElement | (() => HTMLElement);
  /** Event when menu is closing */
  onClose?: (lastClickItem: MenuItem | undefined) => void;
  /** Event when clicking outside (when clickCloseOnOutside is false) */
  onClickOnOutside?: (e: MouseEvent) => void;
  /** Event for MenuBar left focus move */
  onKeyFocusMoveLeft?: () => void;
  /** Event for MenuBar right focus move */
  onKeyFocusMoveRight?: () => void;
}

Functional API

Component API

Vue components for declarative menu construction with full template integration. Ideal for static menus and component-based architectures.

// Main context menu component
declare component ContextMenu {
  props: {
    options: MenuOptions;
    show: boolean;
  };
  events: {
    'update:show': (show: boolean) => void;
    'close': () => void;
  };
}

// Menu item component
declare component ContextMenuItem {
  props: {
    label?: string;
    icon?: string;
    disabled?: boolean;
    hidden?: boolean;
    checked?: boolean;
    shortcut?: string;
  };
  events: {
    'click': (e: MouseEvent | KeyboardEvent) => void;
  };
}

// Menu separator component
declare component ContextMenuSeparator {
  // No props
}

// Menu group component for nested submenus
declare component ContextMenuGroup {
  props: {
    label: string;
  };
  // Contains slot for child menu items
}

Component API

Menu Bar

Traditional horizontal menu bar component for desktop-style applications with dropdown menus.

declare component MenuBar {
  props: {
    options: MenuBarOptions;
  };
}

interface MenuBarOptions extends Omit<MenuOptions, 'x'|'y'|'getContainer'> {
  mini?: boolean;
  barPopDirection?: MenuPopDirection;
}

Menu Bar

Themes and Styling

Built-in theme system with light and dark variants for different UI styles.

type ThemeNames = 
  | 'default' 
  | 'default dark'
  | 'flat'
  | 'flat dark'
  | 'win10'
  | 'win10 dark'
  | 'mac'
  | 'mac dark';

Themes and Styling

Types

Vue Types

// Vue framework types used throughout the API
interface VNode {
  // Vue virtual node for custom renders
}

interface ComputedRef<T> {
  // Vue computed reference
  readonly value: T;
}

interface Slot {
  // Vue slot function
  (...args: any[]): VNode[];
}

Core Types

type MenuPopDirection = 'br'|'b'|'bl'|'tr'|'t'|'tl'|'l'|'r';

interface MenuItem {
  /** Menu item label */
  label?: string | VNode | ((label: string) => VNode);
  /** Menu item icon */
  icon?: string | VNode | ((icon: string) => VNode);
  /** Custom icon font class name */
  iconFontClass?: string;
  /** Reserve fixed-width icon area */
  preserveIconWidth?: boolean;
  /** SVG symbol icon reference */
  svgIcon?: string;
  /** SVG element properties */
  svgProps?: SVGAttributes;
  /** Disable menu item */
  disabled?: boolean | ComputedRef<boolean>;
  /** Hide menu item */
  hidden?: boolean | ComputedRef<boolean>;
  /** Show check mark */
  checked?: boolean | ComputedRef<boolean>;
  /** Shortcut key display text */
  shortcut?: string;
  /** Submenu popup direction */
  direction?: MenuPopDirection;
  /** Adjust submenu position */
  adjustSubMenuPosition?: boolean;
  /** Allow click when has children */
  clickableWhenHasChildren?: boolean;
  /** Close menu on click */
  clickClose?: boolean;
  /** Separator display option */
  divided?: boolean | 'up' | 'down' | 'self';
  /** Custom CSS class */
  customClass?: string;
  /** Maximum height in pixels */
  maxHeight?: number;
  /** Maximum width in pixels */
  maxWidth?: number | string;
  /** Minimum width in pixels */
  minWidth?: number | string;
  /** Click event handler */
  onClick?: (e?: MouseEvent | KeyboardEvent) => void;
  /** Submenu close event */
  onSubMenuClose?: (itemInstance?: MenuItemContext) => void;
  /** Submenu open event */
  onSubMenuOpen?: (itemInstance?: MenuItemContext) => void;
  /** Custom render function */
  customRender?: VNode | ((item: MenuItem) => VNode);
  /** Child menu items */
  children?: MenuItem[];
}

interface ContextMenuInstance {
  /** Close the menu */
  closeMenu(fromItem?: MenuItem | undefined): void;
  /** Check if menu is closed */
  isClosed(): boolean;
  /** Get root menu instance */
  getMenuRef(): ContextSubMenuInstance | undefined;
  /** Get menu dimensions */
  getMenuDimensions(): { width: number, height: number };
}

interface ContextSubMenuInstance {
  /** Get submenu root element */
  getSubmenuRoot(): HTMLElement | undefined;
  /** Get menu container element */
  getMenu(): HTMLElement | undefined;
  /** Get child menu item by index */
  getChildItem(index: number): MenuItemContext | undefined;
  /** Get menu dimensions */
  getMenuDimensions(): { width: number, height: number };
  /** Get current scroll value */
  getScrollValue(): number;
  /** Set scroll value */
  setScrollValue(v: number): void;
  /** Get scroll height */
  getScrollHeight(): number;
  /** Force adjust position */
  adjustPosition(): void;
  /** Get maximum height */
  getMaxHeight(): number;
  /** Get current position */
  getPosition(): { x: number, y: number };
  /** Set position */
  setPosition(x: number, y: number): void;
}

interface MenuItemContext {
  /** Get submenu instance */
  getSubMenuInstance(): ContextSubMenuInstance | undefined;
  /** Show submenu */
  showSubMenu(): boolean;
  /** Hide submenu */
  hideSubMenu(): void;
  /** Get HTML element */
  getElement(): HTMLElement | undefined;
  /** Check if disabled or hidden */
  isDisabledOrHidden(): boolean;
  /** Focus item */
  focus(): void;
  /** Blur item */
  blur(): void;
  /** Click item */
  click(e: MouseEvent | KeyboardEvent): void;
}

interface SVGAttributes {
  [key: string]: any;
}

interface TransitionProps {
  name?: string;
  mode?: 'in-out' | 'out-in' | 'default';
  appear?: boolean;
  css?: boolean;
  type?: 'transition' | 'animation';
  duration?: number | { enter: number; leave: number };
  enterFromClass?: string;
  enterActiveClass?: string;
  enterToClass?: string;
  appearFromClass?: string;
  appearActiveClass?: string;
  appearToClass?: string;
  leaveFromClass?: string;
  leaveActiveClass?: string;
  leaveToClass?: string;
}

docs

component-api.md

functional-api.md

index.md

menu-bar.md

themes.md

tile.json