Dynamic Sidebar Navigation System
Dynamic Sidebar Navigation System
Section titled “Dynamic Sidebar Navigation System”Overview
Section titled “Overview”The dynamic sidebar navigation system provides a flexible, type-safe, and performant way to render navigation menus in the Vue.js application. It supports nested menus, conditional visibility, access control, active state management, and accessibility features.
Architecture
Section titled “Architecture”Core Components
Section titled “Core Components”- AppSidebar.vue: Main container component that orchestrates navigation rendering
- AppSidebarItem.vue: Recursive component for rendering individual navigation items
- types.ts: TypeScript interfaces and type definitions
- utils.ts: Utility functions for navigation processing and validation
- composables/: Reusable composition functions for error handling and navigation filtering
Key Features
Section titled “Key Features”- Declarative Configuration: Define navigation structure using TypeScript interfaces
- Recursive Rendering: Support for unlimited nesting levels
- Conditional Visibility: Show/hide items based on functions or boolean values
- Access Control: Async permission checking with graceful error handling
- Active State Management: Automatic detection and visual feedback for active routes
- Performance Optimization: Memoization, caching, and efficient re-rendering
- Accessibility: ARIA attributes, keyboard navigation, and screen reader support
- Error Boundaries: Graceful degradation when navigation items fail to load
Basic Navigation Structure
Section titled “Basic Navigation Structure”import type { AppSidebarItem } from "@/layouts/components/sidebar/types";import { Home, Settings, Users } from "lucide-vue-next";
const navigationItems: AppSidebarItem[] = [ { title: "Dashboard", url: "/dashboard", icon: Home, isActive: true }, { title: "User Management", icon: Users, items: [ { title: "All Users", url: "/admin/users" }, { title: "User Settings", url: "/admin/settings" } ] }, { title: "Settings", icon: Settings, visible: () => userStore.isAdmin, canAccess: async () => await checkPermission('settings.read'), items: [ { title: "General", url: "/settings/general" }, { title: "Advanced", url: "/settings/advanced" } ] }];
Component Integration
Section titled “Component Integration”<template> <AppSidebar :items="navigationItems" collapsible="icon" variant="sidebar" side="left" /></template>
<script setup lang="ts">import AppSidebar from "@/layouts/components/sidebar/AppSidebar.vue";import { navigationItems } from "./navigation-config";</script>
Configuration Options
Section titled “Configuration Options”AppSidebarItem Interface
Section titled “AppSidebarItem Interface”interface AppSidebarItem { title: string; // Required: Display text url?: string; // Optional: Navigation URL icon?: LucideIcon; // Optional: Lucide icon component isActive?: boolean; // Optional: Force active state tooltip?: string; // Optional: Tooltip text (defaults to title) visible?: boolean | (() => boolean); // Optional: Visibility control canAccess?: () => boolean | Promise<boolean>; // Optional: Access control items?: AppSidebarItem[]; // Optional: Nested items}
Sidebar Props
Section titled “Sidebar Props”interface AppSidebarProps { items: AppSidebarItem[]; // Navigation items array collapsible?: "icon" | "offcanvas" | "none"; // Collapse behavior variant?: "sidebar" | "floating" | "inset"; // Visual variant side?: "left" | "right"; // Sidebar position}
Advanced Features
Section titled “Advanced Features”Conditional Visibility
Section titled “Conditional Visibility”// Boolean visibility{ title: "Admin Panel", visible: false }
// Function-based visibility{ title: "Admin Panel", visible: () => userStore.isAdmin }
// Reactive visibility{ title: "Admin Panel", visible: () => computed(() => userStore.role === 'admin').value }
Access Control
Section titled “Access Control”// Synchronous access control{ title: "User Management", canAccess: () => userStore.hasPermission('users.read')}
// Asynchronous access control{ title: "Admin Panel", canAccess: async () => { const response = await api.checkPermission('admin.access'); return response.allowed; }}
Active State Management
Section titled “Active State Management”// Automatic active state (based on current route){ title: "Dashboard", url: "/dashboard" }
// Manual active state{ title: "Dashboard", url: "/dashboard", isActive: true }
// Parent items automatically expand when children are active{ title: "Settings", items: [ { title: "General", url: "/settings/general" } // Active if current route matches ]}
Performance Considerations
Section titled “Performance Considerations”Caching Strategy
Section titled “Caching Strategy”The system implements multiple levels of caching:
- Active State Cache: Memoizes active state calculations
- Permission Cache: Caches access control results with TTL
- Key Generation Cache: Optimizes Vue’s key-based rendering
Optimization Techniques
Section titled “Optimization Techniques”- Parallel Processing: Access control checks run in parallel
- Lazy Evaluation: Visibility functions called only when needed
- Efficient Re-rendering: Stable keys prevent unnecessary component recreation
- Memory Management: Automatic cache cleanup and size limits
Error Handling
Section titled “Error Handling”Error Boundaries
Section titled “Error Boundaries”The system includes comprehensive error handling:
// Graceful degradation for invalid itemsconst safeItems = safeProcessNavItems(rawItems);
// Error recovery for failed permission checkstry { const hasAccess = await item.canAccess(); return hasAccess;} catch (error) { console.warn(`Access check failed for "${item.title}":`, error); return false; // Fail closed}
Error Types
Section titled “Error Types”- Navigation Errors: Failed to load navigation structure
- Permission Errors: Access control check failures
- Validation Errors: Invalid navigation configuration
- Render Errors: Component rendering failures
Testing
Section titled “Testing”Test Structure
Section titled “Test Structure”sidebar/├── AppSidebar.test.ts # Integration tests├── AppSidebarItem.test.ts # Component tests├── utils.test.ts # Utility function tests├── test-factories.ts # Test data factories├── test-types.ts # Test type definitions└── test-utils.ts # Test helper functions
Testing Patterns
Section titled “Testing Patterns”// Use factories for consistent test dataconst mockItem = createMockSidebarItem({ title: "Test Item", url: "/test"});
// Test async operationsconst asyncItem = createAsyncPermissionItem(true, 50);await waitForAsyncOperations();
// Performance testingconst { duration, passed } = createPerformanceTest( () => renderLargeNavigation(100), 100 // max 100ms);
Accessibility
Section titled “Accessibility”ARIA Support
Section titled “ARIA Support”- aria-expanded: Indicates collapsible state
- aria-label: Descriptive labels for screen readers
- role: Appropriate roles for navigation elements
- aria-current: Marks active navigation items
Keyboard Navigation
Section titled “Keyboard Navigation”- Tab: Navigate between items
- Enter/Space: Activate items and toggle submenus
- Arrow Keys: Navigate within menu hierarchy
- Escape: Close expanded submenus
Migration Guide
Section titled “Migration Guide”From Static Navigation
Section titled “From Static Navigation”// Before: Static navigation<nav> <a href="/dashboard">Dashboard</a> <a href="/settings">Settings</a></nav>
// After: Dynamic navigationconst items: AppSidebarItem[] = [ { title: "Dashboard", url: "/dashboard" }, { title: "Settings", url: "/settings" }];
<AppSidebar :items="items" />
Adding Permissions
Section titled “Adding Permissions”// Add access control to existing itemsconst items: AppSidebarItem[] = [ { title: "Admin Panel", url: "/admin", canAccess: () => userStore.isAdmin // Add this line }];
Best Practices
Section titled “Best Practices”Configuration
Section titled “Configuration”- Keep navigation flat: Avoid excessive nesting (max 3 levels)
- Use meaningful titles: Clear, concise navigation labels
- Implement proper permissions: Always use access control for sensitive areas
- Provide tooltips: Especially for icon-only collapsed states
Performance
Section titled “Performance”- Cache permission results: Avoid repeated API calls
- Use stable keys: Prevent unnecessary re-renders
- Lazy load large menus: Consider virtualization for 100+ items
- Monitor performance: Use built-in performance monitoring
Accessibility
Section titled “Accessibility”- Test with screen readers: Verify ARIA attributes work correctly
- Support keyboard navigation: Ensure all functionality is keyboard accessible
- Provide meaningful labels: Use descriptive aria-label attributes
- Maintain focus management: Proper focus handling in collapsible menus
Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”- Items not showing: Check visibility and access control functions
- Performance issues: Review caching configuration and item count
- Active state not working: Verify URL matching and route configuration
- Permission errors: Check async function error handling
Debug Tools
Section titled “Debug Tools”// Enable debug logginglocalStorage.setItem('sidebar-debug', 'true');
// Check cache statisticsconsole.log(activeStateCache.getStats());
// Validate navigation configurationvalidateNavConfig(navigationItems);
API Reference
Section titled “API Reference”Components
Section titled “Components”AppSidebar
: Main sidebar containerAppSidebarItem
: Recursive navigation item renderer
Composables
Section titled “Composables”useNavigationFiltering
: Handles item filtering and async operationsuseErrorBoundary
: Provides error handling and recoveryuseAccessibility
: Manages ARIA attributes and keyboard navigation
Utilities
Section titled “Utilities”filterNavItems
: Filters items based on visibility and accessisItemActive
: Determines if an item is currently activevalidateNavConfig
: Validates navigation configurationmeasureNavigationPerformance
: Performance monitoring
AppSidebarItem
: Navigation item interfaceAppSidebarProps
: Sidebar component propsResult<T>
: Success/error result type