Files
ui-essentials/projects/demo-ui-essentials/src/app/demos/menu-demo/menu-demo.component.ts
skyai_dev 6f0ab0cf5f Fix SCSS semantic token variable errors across components
- Replace incorrect semantic token names with correct ones:
  • $semantic-border-width-thin → $semantic-border-width-1
  • $semantic-color-border-default → $semantic-color-border-primary
  • $semantic-spacing-content-* → $semantic-spacing-component-*
  • $semantic-typography-body-* → $semantic-typography-font-size-*
  • $semantic-typography-caption-* → $semantic-typography-font-size-*
  • $semantic-motion-easing-standard → $semantic-easing-standard
  • $semantic-color-surface-tertiary → $semantic-color-surface-secondary
  • Various hover color tokens → base color tokens

- Fix typography map usage errors:
  • Replace heading map tokens with individual size tokens
  • $semantic-typography-heading-h* → $semantic-typography-heading-h*-size

- Update affected components:
  • tooltip, divider, progress-circle, range-slider components
  • Related demo components and SCSS files

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-03 07:50:34 +10:00

700 lines
25 KiB
TypeScript

import { Component, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
faUser, faHome, faCog, faEnvelope, faDownload, faShare, faFileExport,
faChartBar, faChartLine, faFileAlt, faShieldAlt, faDatabase, faTrash,
faStar, faBolt, faInfoCircle, faExclamationTriangle, faFolder, faCirclePlus,
faFolderOpen, faEdit, faSave, faTachometerAlt, faProjectDiagram, faPlayCircle,
faCheckCircle, faArchive, faCalendarWeek, faCalendarAlt, faCalendar, faSlidersH,
faPalette, faBell, faQuestionCircle, faSignOutAlt, faBox, faConciergeBell,
faCircle, faRefresh, faToggleOn
} from '@fortawesome/free-solid-svg-icons';
import { faAngular, faGithub } from '@fortawesome/free-brands-svg-icons';
import { MenuItemComponent } from '../../../../../ui-essentials/src/lib/components/navigation/menu/menu-item.component';
import { MenuContainerComponent } from '../../../../../ui-essentials/src/lib/components/navigation/menu/menu-container.component';
import { MenuSubmenuComponent } from '../../../../../ui-essentials/src/lib/components/navigation/menu/menu-submenu.component';
import { MenuItemData } from '../../../../../ui-essentials/src/lib/components/navigation/menu/menu-item.component';
@Component({
selector: 'ui-menu-demo',
standalone: true,
imports: [
CommonModule,
MenuItemComponent,
MenuContainerComponent,
MenuSubmenuComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="menu-demo">
<h2>Menu Component Showcase</h2>
<!-- Basic Menu Items -->
<section class="demo-section">
<h3>Basic Menu Items</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Text Only - Different Sizes</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Small Menu Item' }"
size="sm"
(itemClick)="handleMenuClick('small item', $event)"
/>
<ui-menu-item
[data]="{ label: 'Medium Menu Item' }"
size="md"
(itemClick)="handleMenuClick('medium item', $event)"
/>
<ui-menu-item
[data]="{ label: 'Large Menu Item' }"
size="lg"
(itemClick)="handleMenuClick('large item', $event)"
/>
</ui-menu-container>
</div>
<div class="demo-item">
<h4>Menu States</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Normal Item', active: false }"
(itemClick)="handleMenuClick('normal', $event)"
/>
<ui-menu-item
[data]="{ label: 'Active Item', active: true }"
(itemClick)="handleMenuClick('active', $event)"
/>
<ui-menu-item
[data]="{ label: 'Disabled Item', disabled: true }"
(itemClick)="handleMenuClick('disabled', $event)"
/>
<ui-menu-item
[data]="{ label: 'With Badge', badge: '3' }"
(itemClick)="handleMenuClick('badge', $event)"
/>
</ui-menu-container>
</div>
</div>
</section>
<!-- Icons and Variants -->
<section class="demo-section">
<h3>Icons and Variants</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Left Icons</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Home', icon: faUser }"
iconPosition="left"
(itemClick)="handleMenuClick('home', $event)"
/>
<ui-menu-item
[data]="{ label: 'Settings', icon: faCog }"
iconPosition="left"
(itemClick)="handleMenuClick('settings', $event)"
/>
<ui-menu-item
[data]="{ label: 'Profile', icon: faUser }"
iconPosition="left"
(itemClick)="handleMenuClick('profile', $event)"
/>
<ui-menu-item
[data]="{ label: 'Messages', icon: faEnvelope, badge: '12' }"
iconPosition="left"
(itemClick)="handleMenuClick('messages', $event)"
/>
</ui-menu-container>
</div>
<div class="demo-item">
<h4>Right Icons</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Download', icon: faDownload }"
iconPosition="right"
(itemClick)="handleMenuClick('download', $event)"
/>
<ui-menu-item
[data]="{ label: 'Share', icon: faShare }"
iconPosition="right"
(itemClick)="handleMenuClick('share', $event)"
/>
<ui-menu-item
[data]="{ label: 'Export', icon: faFileExport }"
iconPosition="right"
(itemClick)="handleMenuClick('export', $event)"
/>
</ui-menu-container>
</div>
</div>
</section>
<!-- Circular Icons -->
<section class="demo-section">
<h3>Circular Icons</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Circle Icons - Left</h4>
<ui-menu-container elevation="md" spacing="md" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Dashboard', icon: faChartBar, iconCircle: true }"
iconPosition="left"
variant="primary"
(itemClick)="handleMenuClick('dashboard', $event)"
/>
<ui-menu-item
[data]="{ label: 'Analytics', icon: faChartLine, iconCircle: true }"
iconPosition="left"
variant="secondary"
(itemClick)="handleMenuClick('analytics', $event)"
/>
<ui-menu-item
[data]="{ label: 'Reports', icon: faFileAlt, iconCircle: true }"
iconPosition="left"
(itemClick)="handleMenuClick('reports', $event)"
/>
</ui-menu-container>
</div>
<div class="demo-item">
<h4>Circle Icons - Right</h4>
<ui-menu-container elevation="md" spacing="md" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Security', icon: faShieldAlt, iconCircle: true }"
iconPosition="right"
variant="primary"
(itemClick)="handleMenuClick('security', $event)"
/>
<ui-menu-item
[data]="{ label: 'Backup', icon: faDatabase, iconCircle: true }"
iconPosition="right"
variant="secondary"
(itemClick)="handleMenuClick('backup', $event)"
/>
<ui-menu-item
[data]="{ label: 'Delete', icon: faTrash, iconCircle: true }"
iconPosition="right"
variant="danger"
(itemClick)="handleMenuClick('delete', $event)"
/>
</ui-menu-container>
</div>
</div>
</section>
<!-- Menu Variants -->
<section class="demo-section">
<h3>Menu Variants</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Color Variants</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Default Action', icon: faStar }"
variant="default"
iconPosition="left"
(itemClick)="handleMenuClick('default action', $event)"
/>
<ui-menu-item
[data]="{ label: 'Primary Action', icon: faBolt }"
variant="primary"
iconPosition="left"
(itemClick)="handleMenuClick('primary action', $event)"
/>
<ui-menu-item
[data]="{ label: 'Secondary Action', icon: faInfoCircle }"
variant="secondary"
iconPosition="left"
(itemClick)="handleMenuClick('secondary action', $event)"
/>
<ui-menu-item
[data]="{ label: 'Danger Action', icon: faExclamationTriangle }"
variant="danger"
iconPosition="left"
(itemClick)="handleMenuClick('danger action', $event)"
/>
</ui-menu-container>
</div>
<div class="demo-item">
<h4>With Dividers</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'File Operations', icon: faFolder }"
iconPosition="left"
[showDivider]="true"
(itemClick)="handleMenuClick('file ops', $event)"
/>
<ui-menu-item
[data]="{ label: 'New File', icon: faCirclePlus }"
iconPosition="left"
(itemClick)="handleMenuClick('new file', $event)"
/>
<ui-menu-item
[data]="{ label: 'Open File', icon: faFolderOpen }"
iconPosition="left"
[showDivider]="true"
(itemClick)="handleMenuClick('open file', $event)"
/>
<ui-menu-item
[data]="{ label: 'Edit Operations', icon: faEdit }"
iconPosition="left"
(itemClick)="handleMenuClick('edit ops', $event)"
/>
<ui-menu-item
[data]="{ label: 'Save', icon: faSave }"
iconPosition="left"
(itemClick)="handleMenuClick('save', $event)"
/>
</ui-menu-container>
</div>
</div>
</section>
<!-- Submenu Examples -->
<section class="demo-section">
<h3>Collapsible Submenus</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Navigation Menu</h4>
<ui-menu-container elevation="md" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Dashboard', icon: faTachometerAlt }"
iconPosition="left"
(itemClick)="handleMenuClick('dashboard', $event)"
/>
<ui-menu-submenu
[parentItem]="{ label: 'Projects', icon: faProjectDiagram, hasSubmenu: true }"
iconPosition="left"
[isOpen]="submenuStates['projects']"
(submenuToggled)="toggleSubmenu('projects', $event)"
(parentItemClick)="handleMenuClick('projects parent', $event)"
>
<ui-menu-item
[data]="{ label: 'Active Projects', icon: faPlayCircle }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('active projects', $event)"
/>
<ui-menu-item
[data]="{ label: 'Completed Projects', icon: faCheckCircle }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('completed projects', $event)"
/>
<ui-menu-item
[data]="{ label: 'Archived Projects', icon: faArchive }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('archived projects', $event)"
/>
</ui-menu-submenu>
<ui-menu-submenu
[parentItem]="{ label: 'Reports', icon: faChartBar, hasSubmenu: true }"
iconPosition="left"
[isOpen]="submenuStates['reports']"
(submenuToggled)="toggleSubmenu('reports', $event)"
(parentItemClick)="handleMenuClick('reports parent', $event)"
>
<ui-menu-item
[data]="{ label: 'Weekly Report', icon: faCalendarWeek }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('weekly report', $event)"
/>
<ui-menu-item
[data]="{ label: 'Monthly Report', icon: faCalendarAlt }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('monthly report', $event)"
/>
<ui-menu-item
[data]="{ label: 'Annual Report', icon: faCalendar }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('annual report', $event)"
/>
</ui-menu-submenu>
<ui-menu-item
[data]="{ label: 'Settings', icon: faCog }"
iconPosition="left"
(itemClick)="handleMenuClick('settings', $event)"
/>
</ui-menu-container>
</div>
<div class="demo-item">
<h4>User Menu</h4>
<ui-menu-container elevation="md" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'My Profile', icon: faUser }"
iconPosition="left"
(itemClick)="handleMenuClick('profile', $event)"
/>
<ui-menu-submenu
[parentItem]="{ label: 'Preferences', icon: faSlidersH, hasSubmenu: true }"
iconPosition="left"
[isOpen]="submenuStates['preferences']"
(submenuToggled)="toggleSubmenu('preferences', $event)"
(parentItemClick)="handleMenuClick('preferences parent', $event)"
>
<ui-menu-item
[data]="{ label: 'Theme Settings', icon: faPalette }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('theme', $event)"
/>
<ui-menu-item
[data]="{ label: 'Notifications', icon: faBell }"
iconPosition="left"
size="sm"
[showDivider]="true"
(itemClick)="handleMenuClick('notifications', $event)"
/>
<ui-menu-item
[data]="{ label: 'Privacy', icon: faShieldAlt }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('privacy', $event)"
/>
</ui-menu-submenu>
<ui-menu-item
[data]="{ label: 'Help & Support', icon: faQuestionCircle }"
iconPosition="left"
[showDivider]="true"
(itemClick)="handleMenuClick('help', $event)"
/>
<ui-menu-item
[data]="{ label: 'Sign Out', icon: faSignOutAlt }"
iconPosition="left"
variant="danger"
(itemClick)="handleMenuClick('sign out', $event)"
/>
</ui-menu-container>
</div>
</div>
</section>
<!-- Horizontal Menu -->
<section class="demo-section">
<h3>Horizontal Menu</h3>
<div class="demo-single">
<h4>Navigation Bar Style</h4>
<ui-menu-container
elevation="sm"
spacing="md"
orientation="horizontal"
[rounded]="true"
>
<ui-menu-item
[data]="{ label: 'Home', icon: faHome }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('home nav', $event)"
/>
<ui-menu-item
[data]="{ label: 'Products', icon: faBox }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('products nav', $event)"
/>
<ui-menu-item
[data]="{ label: 'Services', icon: faConciergeBell }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('services nav', $event)"
/>
<ui-menu-item
[data]="{ label: 'About', icon: faInfoCircle }"
iconPosition="left"
size="sm"
(itemClick)="handleMenuClick('about nav', $event)"
/>
<ui-menu-item
[data]="{ label: 'Contact', icon: faEnvelope }"
iconPosition="left"
size="sm"
variant="primary"
(itemClick)="handleMenuClick('contact nav', $event)"
/>
</ui-menu-container>
</div>
</section>
<!-- Dense and Scrollable -->
<section class="demo-section">
<h3>Layout Options</h3>
<div class="demo-grid">
<div class="demo-item">
<h4>Dense Menu</h4>
<ui-menu-container elevation="sm" spacing="xs" [rounded]="true" [dense]="true">
<ui-menu-item
[data]="{ label: 'Compact Item 1', icon: faCircle }"
iconPosition="left"
size="sm"
[dense]="true"
(itemClick)="handleMenuClick('compact 1', $event)"
/>
<ui-menu-item
[data]="{ label: 'Compact Item 2', icon: faCircle }"
iconPosition="left"
size="sm"
[dense]="true"
(itemClick)="handleMenuClick('compact 2', $event)"
/>
<ui-menu-item
[data]="{ label: 'Compact Item 3', icon: faCircle }"
iconPosition="left"
size="sm"
[dense]="true"
(itemClick)="handleMenuClick('compact 3', $event)"
/>
<ui-menu-item
[data]="{ label: 'Compact Item 4', icon: faCircle }"
iconPosition="left"
size="sm"
[dense]="true"
(itemClick)="handleMenuClick('compact 4', $event)"
/>
</ui-menu-container>
</div>
<div class="demo-item">
<h4>Scrollable Menu</h4>
<ui-menu-container
elevation="md"
spacing="sm"
[rounded]="true"
[scrollable]="true"
maxHeight="200px"
>
@for (item of scrollableItems; track item.id) {
<ui-menu-item
[data]="item"
iconPosition="left"
size="md"
(itemClick)="handleMenuClick('scrollable ' + item.id, item)"
/>
}
</ui-menu-container>
</div>
</div>
</section>
<!-- Menu with Links -->
<section class="demo-section">
<h3>Menu with Links</h3>
<div class="demo-single">
<h4>External Links</h4>
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{
label: 'Angular Documentation',
icon: faAngular,
href: 'https://angular.io',
target: '_blank'
}"
iconPosition="left"
(itemClick)="handleMenuClick('angular docs', $event)"
/>
<ui-menu-item
[data]="{
label: 'GitHub Repository',
icon: faGithub,
href: 'https://github.com',
target: '_blank'
}"
iconPosition="left"
(itemClick)="handleMenuClick('github', $event)"
/>
<ui-menu-item
[data]="{
label: 'Material Design',
icon: faPalette,
href: 'https://material.io',
target: '_blank'
}"
iconPosition="left"
(itemClick)="handleMenuClick('material', $event)"
/>
</ui-menu-container>
</div>
</section>
<!-- Usage Examples -->
<section class="demo-section">
<h3>Usage Examples</h3>
<div class="usage-examples">
<h4>Basic Menu Item:</h4>
<pre><code>{{ '<' }}ui-menu-item
[data]="{{ '{' }} label: 'Menu Item', icon: faHome {{ '}' }}"
iconPosition="left"
variant="primary"
(itemClick)="handleClick($event)"{{ '>' }}
{{ '<' }}/ui-menu-item{{ '>' }}</code></pre>
<h4>Menu with Submenu:</h4>
<pre><code>{{ '<' }}ui-menu-submenu
[parentItem]="{{ '{' }} label: 'Parent', hasSubmenu: true {{ '}' }}"
[isOpen]="submenuOpen"
(submenuToggled)="toggleSubmenu($event)"{{ '>' }}
{{ '<' }}ui-menu-item [data]="childItem1"{{ '>' }}{{ '<' }}/ui-menu-item{{ '>' }}
{{ '<' }}ui-menu-item [data]="childItem2"{{ '>' }}{{ '<' }}/ui-menu-item{{ '>' }}
{{ '<' }}/ui-menu-submenu{{ '>' }}</code></pre>
<h4>Menu Container:</h4>
<pre><code>{{ '<' }}ui-menu-container
elevation="md"
spacing="sm"
[rounded]="true"
[scrollable]="true"
maxHeight="300px"{{ '>' }}
{{ '<' }}!-- Menu items here --{{ '>' }}
{{ '<' }}/ui-menu-container{{ '>' }}</code></pre>
</div>
</section>
<!-- Interactive Example -->
<section class="demo-section">
<h3>Interactive Actions</h3>
<div class="interactive-demo">
<ui-menu-container elevation="sm" spacing="sm" [rounded]="true">
<ui-menu-item
[data]="{ label: 'Show Alert', icon: faBell }"
iconPosition="left"
variant="primary"
(itemClick)="showAlert('Menu Alert!')"
/>
<ui-menu-item
[data]="{ label: 'Toggle Demo State', icon: faToggleOn }"
iconPosition="left"
(itemClick)="toggleDemoState()"
/>
<ui-menu-item
[data]="{ label: 'Reset Demo', icon: faRefresh }"
iconPosition="left"
variant="secondary"
(itemClick)="resetDemo()"
/>
</ui-menu-container>
@if (lastClickedItem) {
<div class="demo-feedback">
<strong>Last clicked:</strong> {{ lastClickedItem }}
</div>
}
</div>
</section>
</div>
`,
styleUrls: ['./menu-demo.component.scss']
})
export class MenuDemoComponent {
// FontAwesome icons
faUser = faUser;
faHome = faHome;
faCog = faCog;
faEnvelope = faEnvelope;
faDownload = faDownload;
faShare = faShare;
faFileExport = faFileExport;
faChartBar = faChartBar;
faChartLine = faChartLine;
faFileAlt = faFileAlt;
faShieldAlt = faShieldAlt;
faDatabase = faDatabase;
faTrash = faTrash;
faStar = faStar;
faBolt = faBolt;
faInfoCircle = faInfoCircle;
faExclamationTriangle = faExclamationTriangle;
faFolder = faFolder;
faCirclePlus = faCirclePlus;
faFolderOpen = faFolderOpen;
faEdit = faEdit;
faSave = faSave;
faTachometerAlt = faTachometerAlt;
faProjectDiagram = faProjectDiagram;
faPlayCircle = faPlayCircle;
faCheckCircle = faCheckCircle;
faArchive = faArchive;
faCalendarWeek = faCalendarWeek;
faCalendarAlt = faCalendarAlt;
faCalendar = faCalendar;
faSlidersH = faSlidersH;
faPalette = faPalette;
faBell = faBell;
faQuestionCircle = faQuestionCircle;
faSignOutAlt = faSignOutAlt;
faBox = faBox;
faConciergeBell = faConciergeBell;
faCircle = faCircle;
faRefresh = faRefresh;
faToggleOn = faToggleOn;
faAngular = faAngular;
faGithub = faGithub;
lastClickedItem: string = '';
submenuStates: Record<string, boolean> = {
projects: false,
reports: false,
preferences: false
};
scrollableItems: MenuItemData[] = Array.from({ length: 15 }, (_, i) => ({
id: `item-${i + 1}`,
label: `Scrollable Item ${i + 1}`,
icon: this.faCircle
}));
handleMenuClick(action: string, item: MenuItemData): void {
this.lastClickedItem = `${action} (${item.label})`;
console.log(`Menu clicked: ${action}`, item);
}
toggleSubmenu(key: string, event: { item: MenuItemData; isOpen: boolean }): void {
this.submenuStates[key] = event.isOpen;
console.log(`Submenu ${key} ${event.isOpen ? 'opened' : 'closed'}`);
}
showAlert(message: string): void {
alert(message);
this.lastClickedItem = 'Alert shown';
}
toggleDemoState(): void {
// Toggle all submenus
Object.keys(this.submenuStates).forEach(key => {
this.submenuStates[key] = !this.submenuStates[key];
});
this.lastClickedItem = 'Demo state toggled';
}
resetDemo(): void {
this.lastClickedItem = '';
this.submenuStates = {
projects: false,
reports: false,
preferences: false
};
console.log('Demo reset');
}
}