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

menu-bar.mddocs/

Menu Bar

The MenuBar component provides a traditional horizontal menu bar interface similar to desktop applications. It supports both expanded and collapsed (mini) modes, with dropdown context menus for each menu item.

Capabilities

MenuBar Component

Horizontal menu bar component that displays menu items and shows dropdown context menus when clicked.

declare component MenuBar {
  props: {
    /** Menu bar configuration options */
    options: MenuBarOptions;
  };
  slots: {
    /** Content before menu items */
    prefix: {};
    /** Content after menu items */
    suffix: {};
  };
}

interface MenuBarOptions extends Omit<MenuOptions, 'x'|'y'|'getContainer'> {
  /** Whether the menu bar is in collapsed/mini mode */
  mini?: boolean;
  /** Popup direction for dropdown menus in collapsed state */
  barPopDirection?: MenuPopDirection;
  /** Array of top-level menu items */  
  items?: MenuItem[];
  /** Menu theme */
  theme?: string;
  /** Other MenuOptions properties... */
}

Usage Examples:

<template>
  <!-- Basic menu bar -->
  <menu-bar :options="basicMenuOptions" />
  
  <!-- Menu bar with prefix/suffix slots -->
  <menu-bar :options="advancedMenuOptions">
    <template #prefix>
      <div class="app-logo">
        <img src="/logo.png" alt="App Logo" />
      </div>
    </template>
    
    <template #suffix>
      <div class="menu-actions">
        <button @click="showSettings">Settings</button>
        <button @click="showHelp">Help</button>
      </div>
    </template>
  </menu-bar>
  
  <!-- Collapsed/mini menu bar -->
  <menu-bar :options="miniMenuOptions" />
</template>

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

// Basic menu bar configuration
const basicMenuOptions = ref({
  theme: 'default',
  items: [
    {
      label: 'File',
      children: [
        { label: 'New', shortcut: 'Ctrl+N', onClick: createNew },
        { label: 'Open', shortcut: 'Ctrl+O', onClick: openFile },
        { label: 'Save', shortcut: 'Ctrl+S', onClick: saveFile },
        { divided: true, label: 'Exit', onClick: exitApp }
      ]
    },
    {
      label: 'Edit',
      children: [
        { label: 'Undo', shortcut: 'Ctrl+Z', onClick: undo },
        { label: 'Redo', shortcut: 'Ctrl+Y', onClick: redo },
        { divided: true, label: 'Cut', shortcut: 'Ctrl+X', onClick: cut },
        { label: 'Copy', shortcut: 'Ctrl+C', onClick: copy },
        { label: 'Paste', shortcut: 'Ctrl+V', onClick: paste }
      ]
    },
    {
      label: 'View',
      children: [
        { label: 'Zoom In', shortcut: 'Ctrl++', onClick: zoomIn },
        { label: 'Zoom Out', shortcut: 'Ctrl+-', onClick: zoomOut },
        { label: 'Reset Zoom', shortcut: 'Ctrl+0', onClick: resetZoom }
      ]
    }
  ]
});

// Advanced menu bar with dynamic content
const advancedMenuOptions = ref({
  theme: 'win10',
  minWidth: 150,
  keyboardControl: true,
  items: [
    {
      label: 'File',
      children: [
        { label: 'New Project', onClick: createProject },
        { 
          label: 'Recent Projects', 
          children: getRecentProjects() // Dynamic submenu
        },
        { divided: true, label: 'Import', onClick: importData },
        { label: 'Export', onClick: exportData }
      ]
    },
    {
      label: 'Tools',
      children: [
        { label: 'Preferences', onClick: showPreferences },
        { label: 'Extensions', onClick: showExtensions },
        { 
          label: 'Developer',
          children: [
            { label: 'Console', onClick: showConsole },
            { label: 'Debugger', onClick: showDebugger }
          ]
        }
      ]
    }
  ]
});

// Mini/collapsed menu bar
const miniMenuOptions = ref({
  mini: true,
  theme: 'flat dark',
  barPopDirection: 'bl',
  items: [
    {
      label: 'Menu', // This label is not shown in mini mode
      children: [
        { label: 'File Operations', children: getFileOperations() },
        { label: 'Edit Operations', children: getEditOperations() },
        { label: 'View Options', children: getViewOptions() },
        { divided: true, label: 'Settings', onClick: showSettings },
        { label: 'About', onClick: showAbout }
      ]
    }
  ]
});

function getRecentProjects() {
  return [
    { label: 'Project Alpha', onClick: () => openProject('alpha') },
    { label: 'Project Beta', onClick: () => openProject('beta') },
    { label: 'Project Gamma', onClick: () => openProject('gamma') }
  ];
}
</script>

Menu Bar Modes

The MenuBar component supports two display modes:

Expanded Mode (Default)

Shows all top-level menu items horizontally across the bar.

interface ExpandedMenuBarConfig {
  mini: false; // or undefined
  items: MenuItem[]; // Multiple top-level items displayed
}

Mini/Collapsed Mode

Shows a single menu button that opens a dropdown containing all menu items.

interface MiniMenuBarConfig {
  mini: true;
  items: MenuItem[]; // All items shown in single dropdown
  barPopDirection?: MenuPopDirection; // Direction for dropdown
}

Mode Comparison:

<template>
  <!-- Expanded mode - shows "File", "Edit", "View" horizontally -->
  <menu-bar :options="expandedOptions" />
  
  <!-- Mini mode - shows single hamburger menu button -->
  <menu-bar :options="miniOptions" />
</template>

<script setup>
const expandedOptions = {
  mini: false,
  items: [
    { label: 'File', children: [...] },
    { label: 'Edit', children: [...] },
    { label: 'View', children: [...] }
  ]
};

const miniOptions = {
  mini: true,
  barPopDirection: 'bl',
  items: [
    { 
      label: 'Menu', // Not displayed in mini mode
      children: [
        { label: 'File', children: [...] },
        { label: 'Edit', children: [...] },
        { label: 'View', children: [...] }
      ]
    }
  ]
};
</script>

Advanced Menu Bar Patterns

Responsive Menu Bar

<template>
  <menu-bar :options="responsiveMenuOptions" />
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';

const screenWidth = ref(window.innerWidth);

const responsiveMenuOptions = computed(() => ({
  mini: screenWidth.value < 768, // Mini mode on mobile
  theme: screenWidth.value < 768 ? 'flat' : 'default',
  barPopDirection: 'bl',
  items: getMenuItems()
}));

function updateScreenWidth() {
  screenWidth.value = window.innerWidth;
}

onMounted(() => {
  window.addEventListener('resize', updateScreenWidth);
});

onUnmounted(() => {
  window.removeEventListener('resize', updateScreenWidth);
});
</script>

Menu Bar with State Management

<template>
  <menu-bar :options="stateAwareMenuOptions" />
</template>

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

const isProjectOpen = ref(false);
const hasSelection = ref(false);
const canUndo = ref(false);
const canRedo = ref(false);

const stateAwareMenuOptions = computed(() => ({
  theme: 'win10',
  items: [
    {
      label: 'File',
      children: [
        { label: 'New Project', onClick: createProject },
        { label: 'Open Project', onClick: openProject },
        { 
          label: 'Close Project', 
          disabled: !isProjectOpen.value,
          onClick: closeProject 
        },
        { divided: true, label: 'Save', shortcut: 'Ctrl+S', onClick: save },
        { 
          label: 'Save As...', 
          disabled: !isProjectOpen.value,
          onClick: saveAs 
        }
      ]
    },
    {
      label: 'Edit',
      children: [
        { 
          label: 'Undo', 
          shortcut: 'Ctrl+Z', 
          disabled: !canUndo.value,
          onClick: undo 
        },
        { 
          label: 'Redo', 
          shortcut: 'Ctrl+Y', 
          disabled: !canRedo.value,
          onClick: redo 
        },
        { divided: true },
        { 
          label: 'Cut', 
          shortcut: 'Ctrl+X', 
          disabled: !hasSelection.value,
          onClick: cut 
        },
        { 
          label: 'Copy', 
          shortcut: 'Ctrl+C', 
          disabled: !hasSelection.value,
          onClick: copy 
        }
      ]
    }
  ]
}));
</script>

Menu Bar with Custom Styling

<template>
  <menu-bar 
    :options="customMenuOptions" 
    class="custom-menu-bar"
  >
    <template #prefix>
      <div class="brand-section">
        <img src="/logo.svg" alt="Brand" class="brand-logo" />
        <span class="brand-text">My App</span>
      </div>
    </template>
    
    <template #suffix>
      <div class="user-section">
        <span class="user-name">{{ currentUser.name }}</span>
        <button @click="showUserMenu" class="user-menu-btn">
          <img :src="currentUser.avatar" alt="User" class="user-avatar" />
        </button>
      </div>
    </template>
  </menu-bar>
</template>

<style scoped>
.custom-menu-bar {
  background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 0 16px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.brand-section {
  display: flex;
  align-items: center;
  gap: 8px;
}

.brand-logo {
  width: 24px;
  height: 24px;
}

.user-section {
  display: flex;
  align-items: center;
  gap: 12px;
}

.user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
}
</style>

Menu Bar Configuration

MenuBarOptions Interface

Complete configuration interface extending MenuOptions with menu bar specific properties.

interface MenuBarOptions extends Omit<MenuOptions, 'x'|'y'|'getContainer'> {
  /** Whether the menu bar is in collapsed/mini mode */
  mini?: boolean;
  /** Popup direction for dropdown menus in collapsed state */
  barPopDirection?: MenuPopDirection;
  
  // Inherited from MenuOptions:
  /** Array of top-level menu items */
  items?: MenuItem[];
  /** Menu theme */
  theme?: string;
  /** Z-index for dropdown menus */
  zIndex?: number;
  /** Custom CSS class */
  customClass?: string;
  /** Enable keyboard navigation */
  keyboardControl?: boolean;
  /** Maximum width for dropdown menus */
  maxWidth?: number;
  /** Maximum height for dropdown menus */
  maxHeight?: number;
  /** Minimum width for dropdown menus */
  minWidth?: number;
  /** Custom icon font class */
  iconFontClass?: string;
  /** Reserve icon width for items without icons */
  preserveIconWidth?: boolean;
  /** Menu close callback */
  onClose?: (lastClickItem: MenuItem | undefined) => void;
  /** Keyboard focus movement callbacks */
  onKeyFocusMoveLeft?: () => void;
  onKeyFocusMoveRight?: () => void;
}

MenuBar Keyboard Navigation

The MenuBar component supports keyboard navigation when keyboardControl is enabled:

  • Arrow Left/Right: Navigate between top-level menu items
  • Arrow Down: Open dropdown menu
  • Arrow Up: Close dropdown menu
  • Enter/Space: Activate menu item
  • Escape: Close all menus
<template>
  <menu-bar :options="keyboardMenuOptions" />
</template>

<script setup>
const keyboardMenuOptions = {
  keyboardControl: true,
  items: [...],
  onKeyFocusMoveLeft: () => {
    // Handle left navigation
    console.log('Focus moved left');
  },
  onKeyFocusMoveRight: () => {
    // Handle right navigation  
    console.log('Focus moved right');
  }
};
</script>

docs

component-api.md

functional-api.md

index.md

menu-bar.md

themes.md

tile.json