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

functional-api.mddocs/

Functional API

The functional API provides programmatic control over context menus through global methods. This approach is ideal for dynamic menus, event-driven scenarios, and situations where you need full control over menu display and configuration.

Capabilities

Show Context Menu

Display a context menu at specified coordinates with configurable options and menu items.

/**
 * Show a context menu programmatically
 * @param options - Menu configuration including position, items, and display options
 * @param customSlots - Optional custom rendering slots for menu components
 * @returns ContextMenuInstance for controlling the displayed menu
 */
function showContextMenu(
  options: MenuOptions, 
  customSlots?: Record<string, Slot>
): ContextMenuInstance;

Usage Examples:

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

// Basic context menu
function showBasicMenu(e: MouseEvent) {
  e.preventDefault();
  
  ContextMenu.showContextMenu({
    x: e.x,
    y: e.y,
    items: [
      { label: "Open", onClick: () => console.log("Open clicked") },
      { label: "Save", onClick: () => console.log("Save clicked") },
      { divided: true, label: "Exit", onClick: () => console.log("Exit clicked") }
    ]
  });
}

// Advanced menu with theming and configuration
function showAdvancedMenu(e: MouseEvent) {
  e.preventDefault();
  
  const menuInstance = ContextMenu.showContextMenu({
    x: e.x,
    y: e.y,
    theme: 'win10 dark',
    minWidth: 200,
    maxHeight: 400,
    keyboardControl: true,
    adjustPosition: true,
    items: [
      { 
        label: "File Operations", 
        icon: "folder-icon",
        children: [
          { label: "New File", shortcut: "Ctrl+N", onClick: createFile },
          { label: "Open File", shortcut: "Ctrl+O", onClick: openFile },
          { divided: true, label: "Recent Files", children: getRecentFiles() }
        ]
      },
      { label: "Edit", disabled: !canEdit, onClick: editHandler }
    ],
    onClose: (lastItem) => {
      if (lastItem) {
        console.log(`Menu closed after clicking: ${lastItem.label}`);
      }
    }
  });
  
  // You can control the menu instance
  setTimeout(() => {
    if (!menuInstance.isClosed()) {
      menuInstance.closeMenu();
    }
  }, 5000);
}

// Menu with custom rendering slots
function showCustomMenu(e: MouseEvent) {
  ContextMenu.showContextMenu({
    x: e.x,
    y: e.y,
    items: [{ label: "Custom Item", icon: "star" }]
  }, {
    // Custom item renderer
    itemRender: ({ label, icon, onClick, onMouseEnter, disabled }) => [
      h('div', { 
        class: `my-custom-item ${disabled ? 'disabled' : ''}`,
        onClick: onClick,
        onMouseenter: onMouseEnter
      }, [
        icon ? h('img', { src: icon, class: 'custom-icon' }) : null,
        h('span', { class: 'custom-label' }, label)
      ])
    ]
  });
}

Close Context Menu

Close the currently open context menu programmatically.

/**
 * Close the currently open context menu
 */
function closeContextMenu(): void;

Usage:

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

// Close menu after some action
function handleAction() {
  performAction();
  ContextMenu.closeContextMenu();
}

// Close menu on escape key
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape' && ContextMenu.isAnyContextMenuOpen()) {
    ContextMenu.closeContextMenu();
  }
});

Check Menu Status

Check if any context menu is currently open.

/**
 * Check if any context menu is currently open
 * @returns true if a context menu is open, false otherwise
 */
function isAnyContextMenuOpen(): boolean;

Usage:

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

// Conditional logic based on menu state
function handleGlobalClick() {
  if (ContextMenu.isAnyContextMenuOpen()) {
    // Don't perform action if menu is open
    return;
  }
  
  performGlobalAction();
}

// Prevent multiple menus
function showMenuIfNoneOpen(e: MouseEvent) {
  if (!ContextMenu.isAnyContextMenuOpen()) {
    ContextMenu.showContextMenu({
      x: e.x,
      y: e.y,
      items: getMenuItems()
    });
  }
}

Transform Menu Position

Transform menu display position for scaled containers or special positioning needs.

/**
 * Transform menu position for scaled containers
 * @param element - Target element for position calculation
 * @param x - X coordinate relative to element
 * @param y - Y coordinate relative to element  
 * @param container - Optional container element for position calculation
 * @returns Transformed coordinates for menu display
 */
function transformMenuPosition(
  element: HTMLElement, 
  x: number, 
  y: number, 
  container?: HTMLElement
): { x: number, y: number };

Usage:

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

// Handle scaled containers
function onContextMenuInScaledContainer(e: MouseEvent) {
  e.preventDefault();
  
  const target = e.target as HTMLElement;
  const scaledContainer = document.getElementById('scaled-container');
  
  // Transform position to account for scaling
  const position = ContextMenu.transformMenuPosition(
    target, 
    e.offsetX, 
    e.offsetY, 
    scaledContainer
  );
  
  ContextMenu.showContextMenu({
    x: position.x,
    y: position.y,
    items: getMenuItems(),
    getContainer: () => scaledContainer
  });
}

Configuration Options

MenuOptions Interface

Complete configuration interface for context menu display and behavior.

interface MenuOptions {
  /** Array of menu items to display */
  items?: MenuItem[];
  /** X coordinate for menu display */
  x: number;
  /** Y coordinate for menu display */
  y: number;
  /** X-coordinate offset between submenu and parent */
  xOffset?: number;
  /** Y-coordinate offset between submenu and parent */
  yOffset?: number;
  /** Menu popup direction relative to coordinates */
  direction?: MenuPopDirection;
  /** Z-index for menu display */
  zIndex?: number;
  /** Zoom level for menu display */
  zoom?: number;
  /** Custom CSS class for menu styling */
  customClass?: string;
  /** Enable mouse scroll in menu area */
  mouseScroll?: boolean;
  /** Reserve space for up/down scroll buttons */
  updownButtonSpaceholder?: boolean;
  /** Theme name for menu styling */
  theme?: string;
  /** Class name to ignore click events */
  ignoreClickClassName?: string;
  /** Close menu when clicking outside */
  clickCloseOnOutside?: boolean;
  /** Class name that closes menu when clicked */
  clickCloseClassName?: string;
  /** Custom icon font class name */
  iconFontClass?: string;
  /** Vue transition properties for menu animations */
  menuTransitionProps?: TransitionProps;
  /** Reserve icon width for items without icons */
  preserveIconWidth?: boolean;
  /** Enable keyboard navigation control */
  keyboardControl?: boolean;
  /** Maximum menu width in pixels */
  maxWidth?: number;
  /** Maximum menu height in pixels */
  maxHeight?: number;
  /** Minimum menu width in pixels */
  minWidth?: number;
  /** Close menu when user scrolls */
  closeWhenScroll?: boolean;
  /** Padding for submenu position adjustment */
  adjustPadding?: { x: number, y: number } | number;
  /** Automatically adjust menu position to prevent overflow */
  adjustPosition?: boolean;
  /** Custom container element for menu mounting */
  getContainer?: HTMLElement | (() => HTMLElement);
  /** Callback when menu is closing */
  onClose?: (lastClickItem: MenuItem | undefined) => void;
  /** Callback when user clicks outside (when clickCloseOnOutside is false) */
  onClickOnOutside?: (e: MouseEvent) => void;
  /** Callback for left keyboard focus movement (MenuBar use) */
  onKeyFocusMoveLeft?: () => void;
  /** Callback for right keyboard focus movement (MenuBar use) */
  onKeyFocusMoveRight?: () => void;
}

MenuItem Interface

Configuration for individual menu items including appearance, behavior, and submenu support.

interface MenuItem {
  /** Menu item label text or custom render function */
  label?: string | VNode | ((label: string) => VNode);
  /** Menu item icon (CSS class, image path, or VNode) */
  icon?: string | VNode | ((icon: string) => VNode);
  /** Custom icon font class name */
  iconFontClass?: string;
  /** Reserve icon width for this item */
  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 on menu item */
  checked?: boolean | ComputedRef<boolean>;
  /** Shortcut key text display */
  shortcut?: string;
  /** Submenu popup direction */
  direction?: MenuPopDirection;
  /** Auto-adjust submenu position */
  adjustSubMenuPosition?: boolean;
  /** Allow click event when item has children */
  clickableWhenHasChildren?: boolean;
  /** Close menu when this item is clicked */
  clickClose?: boolean;
  /** Separator configuration */
  divided?: boolean | 'up' | 'down' | 'self';
  /** Custom CSS class for item */
  customClass?: string;
  /** Maximum height for submenu */
  maxHeight?: number;
  /** Maximum width for submenu */
  maxWidth?: number | string;
  /** Minimum width for submenu */
  minWidth?: number | string;
  /** Click event handler */
  onClick?: (e?: MouseEvent | KeyboardEvent) => void;
  /** Submenu close event handler */
  onSubMenuClose?: (itemInstance?: MenuItemContext) => void;
  /** Submenu open event handler */
  onSubMenuOpen?: (itemInstance?: MenuItemContext) => void;
  /** Custom render function for item */
  customRender?: VNode | ((item: MenuItem) => VNode);
  /** Child menu items for submenu */
  children?: MenuItem[];
}

Context Menu Instance

The returned instance from showContextMenu provides methods to control the displayed menu.

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

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

docs

component-api.md

functional-api.md

index.md

menu-bar.md

themes.md

tile.json