--- name: angular-cdk-integration description: Create components using Angular CDK utilities including drag-drop, overlay, portal, scrolling, a11y, clipboard, and platform detection for ng-events project license: MIT --- # Angular CDK Integration Skill This skill guides the creation of components and features using Angular CDK (@angular/cdk) utilities in the ng-events construction site management system. ## When to Use This Skill **Triggers**: "Angular CDK", "drag and drop", "overlay", "portal", "virtual scroll", "accessibility", "clipboard", "platform detection", "CDK utilities" Use this skill when: - Implementing drag-and-drop functionality - Creating overlays, tooltips, or popovers - Building virtual scrolling lists - Managing focus and accessibility - Detecting platform/browser capabilities - Working with clipboard operations - Managing scrolling behavior ## Core CDK Modules ### 1. Drag and Drop (@angular/cdk/drag-drop) **Purpose**: Create draggable elements and drop zones ```typescript import { Component } from '@angular/core'; import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; import { CommonModule } from '@angular/common'; import { CdkDropList, CdkDrag } from '@angular/cdk/drag-drop'; @Component({ selector: 'app-task-board', standalone: true, imports: [CommonModule, CdkDropList, CdkDrag], template: `

To Do

@for (task of todo; track task.id) {
{{ task.title }}
}

In Progress

@for (task of inProgress; track task.id) {
{{ task.title }}
}

Done

@for (task of done; track task.id) {
{{ task.title }}
}
`, styles: [` .task-board { display: flex; gap: 20px; } .column { flex: 1; min-height: 400px; background: #f5f5f5; padding: 16px; border-radius: 4px; } .task-card { background: white; padding: 12px; margin-bottom: 8px; border-radius: 4px; cursor: move; } .task-card:active { box-shadow: 0 5px 5px -3px rgba(0,0,0,.2); } .drag-placeholder { background: #ccc; border: dotted 2px #999; height: 40px; transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); } `] }) export class TaskBoardComponent { todo = [ { id: '1', title: 'Task 1' }, { id: '2', title: 'Task 2' } ]; inProgress = [ { id: '3', title: 'Task 3' } ]; done = [ { id: '4', title: 'Task 4' } ]; drop(event: CdkDragDrop) { if (event.previousContainer === event.container) { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else { transferArrayItem( event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex ); } } } ``` ### 2. Overlay (@angular/cdk/overlay) **Purpose**: Create floating panels and popups ```typescript import { Component, inject } from '@angular/core'; import { Overlay, OverlayRef } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; @Component({ selector: 'app-menu-trigger', standalone: true, template: ` ` }) export class MenuTriggerComponent { private overlay = inject(Overlay); private overlayRef: OverlayRef | null = null; openMenu(): void { if (this.overlayRef) { this.overlayRef.dispose(); this.overlayRef = null; return; } const positionStrategy = this.overlay .position() .flexibleConnectedTo(this.elementRef) .withPositions([ { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' } ]); this.overlayRef = this.overlay.create({ positionStrategy, scrollStrategy: this.overlay.scrollStrategies.reposition(), hasBackdrop: true, backdropClass: 'cdk-overlay-transparent-backdrop' }); const menuPortal = new ComponentPortal(MenuComponent); this.overlayRef.attach(menuPortal); // Close on backdrop click this.overlayRef.backdropClick().subscribe(() => { this.overlayRef?.dispose(); this.overlayRef = null; }); } } ``` ### 3. Virtual Scrolling (@angular/cdk/scrolling) **Purpose**: Efficiently render large lists ```typescript import { Component, signal } from '@angular/core'; import { ScrollingModule } from '@angular/cdk/scrolling'; import { CommonModule } from '@angular/common'; @Component({ selector: 'app-task-list-virtual', standalone: true, imports: [CommonModule, ScrollingModule], template: `

{{ task.title }}

{{ task.description }}

`, styles: [` .viewport { height: 400px; width: 100%; border: 1px solid #ccc; } .task-item { height: 50px; padding: 10px; border-bottom: 1px solid #eee; } `] }) export class TaskListVirtualComponent { tasks = signal(Array.from({ length: 10000 }, (_, i) => ({ id: `task-${i}`, title: `Task ${i}`, description: `Description for task ${i}` }))); } ``` ### 4. Clipboard (@angular/cdk/clipboard) **Purpose**: Copy text to clipboard ```typescript import { Component, inject } from '@angular/core'; import { Clipboard, ClipboardModule } from '@angular/cdk/clipboard'; @Component({ selector: 'app-share-link', standalone: true, imports: [ClipboardModule], template: `
@if (copied) { Copied! }
` }) export class ShareLinkComponent { private clipboard = inject(Clipboard); shareLink = 'https://ng-events.com/blueprints/123'; copied = false; onCopied(success: boolean): void { if (success) { this.copied = true; setTimeout(() => this.copied = false, 2000); } } } ``` ### 5. Platform Detection (@angular/cdk/platform) **Purpose**: Detect browser and platform capabilities ```typescript import { Component, inject, OnInit } from '@angular/core'; import { Platform } from '@angular/cdk/platform'; @Component({ selector: 'app-platform-aware', standalone: true, template: `

Platform Information

` }) export class PlatformAwareComponent implements OnInit { private platform = inject(Platform); browser = ''; isMobile = false; isIOS = false; isAndroid = false; ngOnInit(): void { this.isMobile = this.platform.IOS || this.platform.ANDROID; this.isIOS = this.platform.IOS; this.isAndroid = this.platform.ANDROID; if (this.platform.FIREFOX) this.browser = 'Firefox'; else if (this.platform.EDGE) this.browser = 'Edge'; else if (this.platform.SAFARI) this.browser = 'Safari'; else if (this.platform.WEBKIT) this.browser = 'WebKit'; else this.browser = 'Unknown'; } } ``` ## Integration Checklist When using Angular CDK: - [ ] Import specific CDK modules (not full @angular/cdk) - [ ] Use standalone components with CDK directives - [ ] Implement proper cleanup (subscriptions, overlays) - [ ] Test accessibility with screen readers - [ ] Handle mobile/touch interactions - [ ] Consider performance (virtual scrolling for lists >100 items) - [ ] Integrate with Blueprint multi-tenancy when needed - [ ] Follow three-layer architecture (CDK in UI layer only) ## Best Practices ### DO ✅ - Use CDK for complex UI interactions - Leverage virtual scrolling for large datasets - Use overlay service for tooltips/menus - Detect platform for feature support - Clean up overlays and portals on destroy ### DON'T ❌ - Use CDK in services or repositories (UI layer only) - Create overlays without disposal logic - Skip accessibility considerations - Ignore mobile touch events ## References - [Angular CDK Documentation](https://material.angular.io/cdk/categories) - [Drag and Drop Guide](https://material.angular.io/cdk/drag-drop/overview) - [Virtual Scrolling Guide](https://material.angular.io/cdk/scrolling/overview) --- **Version**: 1.0.0 **Compatible with**: @angular/cdk 20.x, Angular 20.3.x **Last Updated**: 2025-12-25