Menu

Ecosistema completo para organización y gestión de contenido con interfaces espaciales

UX Menu

The UX Menu component is a versatile navigation and interaction tool that provides a consistent way to display menu options to users. It supports various layouts, nested items, badges, icons, and theme options while maintaining a seamless user experience.

Features

Basic Usage

<app-ux-menu
  [id]="'main-navigation'"
  [items]="menuItems"
  [config]="menuConfig"
  (itemSelected)="onMenuItemSelected($event)">
</app-ux-menu>
import { Component } from '@angular/core';
import { UxMenuComponent, UxMenuItem, UxMenuConfig } from '@ux-widgets';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [UxMenuComponent],
  // ...
})
export class MyComponent {
  // Menu configuration
  menuConfig: UxMenuConfig = {
    id: 'main-navigation',
    position: 'left',
    theme: 'light',
    showIcons: true,
    showBadges: true,
    allowMultipleExpanded: false,
    animationDuration: 300,
    closeOnNavigation: true,
    hasOverlay: true,
    overlayOpacity: 0.5,
    backdropBlur: true,
    zIndex: 1000,
    persistConfig: true,
    autoLoadSavedConfig: true
  };
  
  // Menu items
  menuItems: UxMenuItem[] = [
    {
      id: 'dashboard',
      title: 'Dashboard',
      icon: 'dashboard',
      route: '/dashboard'
    },
    {
      id: 'projects',
      title: 'Projects',
      icon: 'folder',
      badge: '8',
      badgeColor: '#4caf50',
      children: [
        {
          id: 'my-projects',
          title: 'My Projects',
          icon: 'folder_special',
          route: '/projects/my-projects'
        },
        {
          id: 'shared',
          title: 'Shared with Me',
          icon: 'folder_shared',
          route: '/projects/shared',
          badge: 'New',
          badgeColor: '#2196f3'
        }
      ]
    }
  ];
  
  // Menu item selection handler
  onMenuItemSelected(item: UxMenuItem) {
    console.log('Selected menu item:', item);
    // Handle navigation or action
  }
}

IndexedDB Integration

The UX Menu uses IndexedDB to save and restore user's menu configuration, ensuring a consistent experience across sessions. This is particularly important for menus with expandable sections, where users expect their navigation state to be preserved.

How IndexedDB Storage Works

The menu uses a dedicated storage service (UxMenuStorageService) that handles all database operations:

  1. Database Initialization:

    • The service creates a database called ux-menu-db with a store named menu-configurations
    • Each configuration is identified by a unique menu ID
  2. Data Structure:

    • Menu configurations are stored with the following structure:
      {
        id: string;           // Menu ID
        [configProperties];   // All properties from UxMenuConfig
        _menuItems: UxMenuItem[]; // Optional: Menu items if stored together
        lastSaved: string;    // Timestamp
      }
      
  3. Saving Process:

    • When a user interacts with the menu (expands sections, changes theme, etc.), changes are recorded
    • If persistConfig is enabled, these changes are saved to IndexedDB
    • The service handles queuing multiple save operations to prevent conflicts
    • Robust error handling prevents data corruption
  4. Loading Process:

    • When a menu with the same ID is initialized and autoLoadSavedConfig is true, the saved configuration is automatically loaded
    • This happens transparently to restore the user's previous state

Ensuring Proper Functionality

When implementing the UX Menu with IndexedDB storage, follow these steps to ensure everything works correctly:

1. Provide Unique IDs

Always provide a unique ID for each menu instance to avoid configuration conflicts:

menuConfig: UxMenuConfig = {
  id: 'app-main-navigation', // Unique ID
  // Other configuration...
};

2. Handle Database Initialization

Menu operations should wait for the database to be initialized:

import { UxMenuService, UxMenuStorageService } from '@ux-widgets';

constructor(
  private menuService: UxMenuService,
  private menuStorage: UxMenuStorageService
) {}

ngOnInit() {
  // Wait for database to be ready
  this.menuStorage.isDatabaseReady().pipe(
    filter(ready => ready),
    take(1)
  ).subscribe(() => {
    // Safe to perform menu operations
    this.initializeMenu();
  });
}

3. Implement Proper Error Handling

IndexedDB operations can fail for various reasons. Implement proper error handling:

saveMenuState() {
  this.menuService.getMenuState(this.menuId).pipe(
    switchMap(state => {
      return this.menuStorage.saveMenuConfig(state);
    }),
    catchError(error => {
      console.error('Failed to save menu state', error);
      // Implement fallback if needed
      return of(false);
    })
  ).subscribe(success => {
    if (success) {
      console.log('Menu state saved successfully');
    } else {
      console.warn('Menu state could not be saved');
    }
  });
}

4. Test Edge Cases

Test your menu implementation in various scenarios:

5. Implement Fallbacks

Always provide fallback mechanisms for cases where IndexedDB is unavailable:

// Check if IndexedDB is available
if (!window.indexedDB) {
  console.warn('IndexedDB not supported in this browser. Menu state will not persist.');
  
  // Disable persistence to prevent errors
  this.menuConfig = {
    ...this.menuConfig,
    persistConfig: false,
    autoLoadSavedConfig: false
  };
  
  // Optionally, try to use localStorage as fallback
  this.setupLocalStorageFallback();
}

By following these guidelines, you can ensure that the UX Menu with IndexedDB storage provides a reliable and consistent user experience across different environments and usage scenarios.