Ux Floating Menu
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
UxFloatingMenu Component
Overview
The UxFloatingMenuComponent is a modern, performant floating menu component designed for displaying action buttons in a fixed position on the screen. It features a glassmorphism design, smooth animations, and full accessibility support.
Features
- ✅ Signal-based Architecture: Built with Angular 20 signals for optimal reactivity
- ✅ Dynamic Configuration: Fully configurable via input properties
- ✅ Performance Optimized: OnPush change detection and conditional rendering
- ✅ Accessibility Compliant: WCAG 2.1 AA compliant with ARIA attributes
- ✅ Keyboard Navigation: Full keyboard support (Arrow keys, Escape)
- ✅ Icon Integration: Seamlessly integrates with ux-icon component
- ✅ Notification Badges: Display notification counts on menu items
- ✅ Responsive Design: Adapts to different screen sizes
- ✅ Glassmorphism Effect: Modern backdrop-blur styling
- ✅ Animation Support: Smooth transitions with reduced-motion support
Installation
Import the Component
The component is part of the @ux-menu library. Use direct imports for reliability:
import { UxFloatingMenuComponent } from 'libs/ux-menu/src/lib/components/ux-floating-menu/ux-floating-menu.component';
import { UxFloatingMenuItem } from 'libs/ux-menu/src/lib/models/ux-floating-menu.models';
Add to Component Imports
@Component({
selector: 'app-my-component',
standalone: true,
imports: [UxFloatingMenuComponent],
// ...
})
export class MyComponent {}
Basic Usage
Simple Example
import { Component, signal } from '@angular/core';
import { UxFloatingMenuComponent } from 'libs/ux-menu/src/lib/components/ux-floating-menu/ux-floating-menu.component';
import { UxFloatingMenuItem } from 'libs/ux-menu/src/lib/models/ux-floating-menu.models';
@Component({
selector: 'app-example',
standalone: true,
imports: [UxFloatingMenuComponent],
template: `
<ux-floating-menu
[items]="menuItems()"
position="bottom-right" />
`
})
export class ExampleComponent {
menuItems = signal<UxFloatingMenuItem[]>([
{
id: 'ai-assistant',
icon: 'svg/robot',
label: 'AI Assistant',
onClick: () => this.openAIAssistant()
},
{
id: 'settings',
icon: 'svg/settings',
label: 'Settings',
onClick: () => this.openSettings()
}
]);
openAIAssistant(): void {
console.log('Opening AI Assistant...');
}
openSettings(): void {
console.log('Opening Settings...');
}
}
Advanced Usage
With Notifications and Active States
menuItems = signal<UxFloatingMenuItem[]>([
{
id: 'notifications',
icon: 'svg/bell',
label: 'Notifications',
notificationCount: 5,
onClick: (item) => this.handleNotifications(item)
},
{
id: 'messages',
icon: 'svg/message',
label: 'Messages',
active: true, // Currently active
notificationCount: 12,
onClick: (item) => this.handleMessages(item)
},
{
id: 'archive',
icon: 'svg/archive',
label: 'Archive',
disabled: true, // Disabled state
tooltip: 'Archive feature coming soon'
}
]);
Custom Configuration
<ux-floating-menu
[items]="menuItems()"
position="top-left"
[config]="{
showWhenHidden: true,
animationDuration: 400,
gap: '12px'
}" />
With Custom Styling
menuItems = signal<UxFloatingMenuItem[]>([
{
id: 'custom',
icon: 'svg/star',
label: 'Custom',
styleClass: 'my-custom-button-class',
onClick: () => this.handleCustomAction()
}
]);
Add custom styles in your component's SCSS:
::ng-deep {
.my-custom-button-class {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
border-color: rgba(102, 126, 234, 0.5) !important;
}
}
Dynamic Menu Items
import { Component, signal, computed } from '@angular/core';
@Component({
// ...
})
export class DynamicMenuComponent {
private hasNewMessages = signal(true);
private messageCount = signal(3);
private isAdminMode = signal(false);
menuItems = computed<UxFloatingMenuItem[]>(() => {
const items: UxFloatingMenuItem[] = [
{
id: 'messages',
icon: 'svg/message',
label: 'Messages',
notificationCount: this.hasNewMessages() ? this.messageCount() : 0,
onClick: () => this.openMessages()
},
{
id: 'help',
icon: 'svg/help',
label: 'Help',
onClick: () => this.openHelp()
}
];
// Conditionally add admin item
if (this.isAdminMode()) {
items.push({
id: 'admin',
icon: 'svg/shield',
label: 'Admin Panel',
onClick: () => this.openAdminPanel()
});
}
return items;
});
}
API Reference
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
items |
UxFloatingMenuItem[] |
required | Array of menu items to display |
position |
UxFloatingMenuPosition |
'bottom-right' |
Position of the menu on screen |
config |
UxFloatingMenuConfig |
{} |
Additional configuration options |
UxFloatingMenuItem Interface
interface UxFloatingMenuItem {
id: string; // Unique identifier
icon: string; // Icon ID for ux-icon component
label: string; // Display label
onClick?: (item: UxFloatingMenuItem, event?: Event) => void; // Click handler
active?: boolean; // Active/selected state
notificationCount?: number; // Notification badge count
disabled?: boolean; // Disabled state
tooltip?: string; // Tooltip text
ariaLabel?: string; // Accessibility label
styleClass?: string; // Custom CSS classes
hidden?: boolean; // Hide item
}
UxFloatingMenuPosition Type
type UxFloatingMenuPosition = 'top-right' | 'bottom-right' | 'top-left' | 'bottom-left';
UxFloatingMenuConfig Interface
interface UxFloatingMenuConfig {
position?: UxFloatingMenuPosition; // Menu position (overridden by position input)
showWhenHidden?: boolean; // Show toggle button
animationDuration?: number; // Animation duration in ms
gap?: string; // Gap between items (CSS value)
}
Methods
The component provides these public methods:
// Toggle menu visibility
toggleVisibility(): void
// Get total notification count
getTotalNotifications(): number
// Check if any item is active
hasActiveItem(): boolean
Accessibility Features
The component is fully accessible and includes:
- ARIA Labels: All interactive elements have proper ARIA labels
- Keyboard Navigation:
Arrow Up/Down: Navigate through menu itemsEscape: Close menu (when toggle is enabled)Enter/Space: Activate focused item
- Focus Management: Clear focus indicators with
:focus-visible - Screen Reader Support: Notification counts and states are announced
- High Contrast Mode: Enhanced visibility in high contrast mode
- Reduced Motion: Respects
prefers-reduced-motionsetting
Styling Customization
CSS Variables
The component uses CSS variables for easy theming:
:root {
--ux-floating-menu-gap: 8px;
--ux-text-color: #e2e8f0;
--ux-focus-color: #3b82f6;
}
Custom Styles
You can override component styles using the styleClass property on individual items or by targeting component classes:
// In your component's styles
::ng-deep {
.ux-floating-menu__item {
// Custom item styles
}
.ux-floating-menu__badge {
// Custom badge styles
}
}
Performance Considerations
- Uses
OnPushchange detection strategy - Only renders visible items (filtered through computed signal)
- Uses
@ifcontrol flow for optimal rendering - Leverages
trackin@forloops for efficient updates - No setTimeout or setInterval usage
- CSS-based animations
Browser Support
- Chrome/Edge: ✅ Full support
- Firefox: ✅ Full support
- Safari: ✅ Full support (with -webkit- prefixes for backdrop-filter)
- Mobile browsers: ✅ Responsive design included
Examples
Complete Real-World Example
import { Component, signal } from '@angular/core';
import { UxFloatingMenuComponent } from 'libs/ux-menu/src/lib/components/ux-floating-menu/ux-floating-menu.component';
import { UxFloatingMenuItem } from 'libs/ux-menu/src/lib/models/ux-floating-menu.models';
@Component({
selector: 'app-dashboard',
standalone: true,
imports: [UxFloatingMenuComponent],
template: `
<div class="dashboard">
<!-- Your dashboard content -->
<ux-floating-menu
[items]="floatingActions()"
position="bottom-right"
[config]="{ showWhenHidden: false }" />
</div>
`
})
export class DashboardComponent {
showAI = signal(false);
showLibrary = signal(false);
aiSuggestions = signal(3);
floatingActions = signal<UxFloatingMenuItem[]>([
{
id: 'ai-assistant',
icon: 'svg/robot',
label: 'AI Assistant',
notificationCount: this.aiSuggestions(),
active: this.showAI(),
onClick: () => this.toggleAI(),
ariaLabel: 'Toggle AI Assistant'
},
{
id: 'library',
icon: 'svg/library',
label: 'Component Library',
active: this.showLibrary(),
onClick: () => this.toggleLibrary(),
ariaLabel: 'Toggle Component Library'
},
{
id: 'export',
icon: 'svg/download',
label: 'Export',
onClick: () => this.handleExport(),
tooltip: 'Export your project'
},
{
id: 'reset',
icon: 'svg/refresh',
label: 'Reset View',
onClick: () => this.resetView(),
tooltip: 'Reset to default view'
}
]);
toggleAI(): void {
this.showAI.update(value => !value);
this.updateItemState('ai-assistant', this.showAI());
}
toggleLibrary(): void {
this.showLibrary.update(value => !value);
this.updateItemState('library', this.showLibrary());
}
updateItemState(id: string, active: boolean): void {
this.floatingActions.update(items =>
items.map(item =>
item.id === id ? { ...item, active } : item
)
);
}
handleExport(): void {
console.log('Exporting project...');
}
resetView(): void {
console.log('Resetting view...');
}
}
Related Components
- UxMenu - Standard menu component
- UxMenuDropdown - Dropdown menu component
- UxIcon - Icon component used for menu icons
Troubleshooting
Icons not displaying
Make sure the icon IDs you're using exist in your icon service:
// Verify icon exists
icon: 'svg/robot' // Must be available in icon service
Menu not positioning correctly
Check that the parent container allows fixed positioning:
.parent-container {
position: relative; // or static, but not absolute/fixed
z-index: 1; // Lower than menu's z-index (100)
}
Styles not applying
Use direct imports and ensure your build includes the component:
import { UxFloatingMenuComponent } from 'libs/ux-menu/src/lib/components/ux-floating-menu/ux-floating-menu.component';
Changelog
Version 1.0.0 (October 2024)
- Initial release
- Signal-based implementation
- Full accessibility support
- Glassmorphism design
- Keyboard navigation
- Notification badges
- Responsive design