0
# Overlay
1
2
PrimeNG provides 8 overlay components for creating modals, dialogs, tooltips, and popup interfaces that appear above the main content layer.
3
4
## Dialog Components
5
6
### Dialog
7
8
Modal dialog window with header, content, and footer sections.
9
10
```typescript { .api }
11
// Import
12
import { Dialog } from 'primeng/dialog';
13
// Module: DialogModule
14
15
// Component Interface
16
interface DialogProps {
17
header?: string;
18
draggable?: boolean;
19
resizable?: boolean;
20
positionLeft?: number;
21
positionTop?: number;
22
contentStyle?: any;
23
contentStyleClass?: string;
24
modal?: boolean;
25
closeOnEscape?: boolean;
26
dismissableMask?: boolean;
27
rtl?: boolean;
28
closable?: boolean;
29
responsive?: boolean;
30
appendTo?: any;
31
breakpoints?: any;
32
style?: any;
33
styleClass?: string;
34
maskStyleClass?: string;
35
showHeader?: boolean;
36
breakpoint?: string;
37
blockScroll?: boolean;
38
autoZIndex?: boolean;
39
baseZIndex?: number;
40
minX?: number;
41
minY?: number;
42
focusOnShow?: boolean;
43
maximizable?: boolean;
44
keepInViewport?: boolean;
45
focusTrap?: boolean;
46
transitionOptions?: string;
47
closeIcon?: string;
48
closeAriaLabel?: string;
49
closeTabindex?: string;
50
minimizeIcon?: string;
51
maximizeIcon?: string;
52
}
53
54
// Events
55
interface DialogShowEvent {
56
originalEvent?: Event;
57
}
58
59
interface DialogHideEvent {
60
originalEvent?: Event;
61
}
62
63
interface DialogResizeInitEvent {
64
originalEvent: MouseEvent;
65
element: HTMLElement;
66
}
67
68
interface DialogResizeEndEvent {
69
originalEvent: MouseEvent;
70
element: HTMLElement;
71
}
72
73
interface DialogDragEndEvent {
74
originalEvent: MouseEvent;
75
element: HTMLElement;
76
}
77
78
// Usage
79
@Component({
80
template: `
81
<!-- Basic Dialog -->
82
<p-dialog
83
header="Header"
84
[(visible)]="displayBasic"
85
[style]="{width: '50vw'}"
86
(onShow)="onShow($event)"
87
(onHide)="onHide($event)">
88
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
89
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
90
<ng-template pTemplate="footer">
91
<p-button icon="pi pi-check" (onClick)="displayBasic=false" label="Ok" styleClass="p-button-text"></p-button>
92
</ng-template>
93
</p-dialog>
94
95
<!-- Maximizable Dialog -->
96
<p-dialog
97
header="Header"
98
[(visible)]="displayMaximizable"
99
[modal]="true"
100
[style]="{width: '50vw'}"
101
[maximizable]="true">
102
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
103
<ng-template pTemplate="footer">
104
<p-button icon="pi pi-times" (onClick)="displayMaximizable=false" label="Cancel" styleClass="p-button-text"></p-button>
105
<p-button icon="pi pi-check" (onClick)="displayMaximizable=false" label="Save"></p-button>
106
</ng-template>
107
</p-dialog>
108
109
<!-- Position Dialog -->
110
<p-dialog
111
header="Header"
112
[(visible)]="displayPosition"
113
[modal]="true"
114
[style]="{width: '50vw'}"
115
[position]="position"
116
[draggable]="false"
117
[resizable]="false">
118
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
119
<ng-template pTemplate="footer">
120
<p-button icon="pi pi-check" (onClick)="displayPosition=false" label="Ok" styleClass="p-button-text"></p-button>
121
</ng-template>
122
</p-dialog>
123
124
<!-- Custom Header Dialog -->
125
<p-dialog
126
[(visible)]="displayCustomHeader"
127
[modal]="true"
128
[style]="{width: '50vw'}"
129
[draggable]="false"
130
[resizable]="false">
131
<ng-template pTemplate="header">
132
<div class="flex align-items-center gap-2">
133
<p-avatar image="assets/showcase/images/demo/avatar/amyelsner.png" shape="circle"></p-avatar>
134
<span class="font-bold white-space-nowrap">Amy Elsner</span>
135
</div>
136
</ng-template>
137
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
138
<ng-template pTemplate="footer">
139
<p-button icon="pi pi-times" (onClick)="displayCustomHeader=false" label="Cancel" styleClass="p-button-text"></p-button>
140
<p-button icon="pi pi-check" (onClick)="displayCustomHeader=false" label="Save"></p-button>
141
</ng-template>
142
</p-dialog>
143
144
<div class="card flex justify-content-center gap-2 flex-wrap">
145
<p-button (onClick)="showDialog()" icon="pi pi-external-link" label="Show"></p-button>
146
<p-button (onClick)="showMaximizableDialog()" icon="pi pi-window-maximize" label="Maximizable"></p-button>
147
<p-button (onClick)="showPositionDialog('top')" icon="pi pi-arrow-up" label="Top" styleClass="p-button-help"></p-button>
148
</div>
149
`
150
})
151
export class DialogComponent {
152
displayBasic: boolean = false;
153
displayMaximizable: boolean = false;
154
displayPosition: boolean = false;
155
displayCustomHeader: boolean = false;
156
position: string = 'center';
157
158
showDialog() {
159
this.displayBasic = true;
160
}
161
162
showMaximizableDialog() {
163
this.displayMaximizable = true;
164
}
165
166
showPositionDialog(position: string) {
167
this.position = position;
168
this.displayPosition = true;
169
}
170
171
onShow(event: DialogShowEvent) {
172
console.log('Dialog shown');
173
}
174
175
onHide(event: DialogHideEvent) {
176
console.log('Dialog hidden');
177
}
178
}
179
```
180
181
### ConfirmDialog
182
183
Confirmation dialog with accept/reject actions.
184
185
```typescript { .api }
186
// Import
187
import { ConfirmDialog } from 'primeng/confirmdialog';
188
import { ConfirmationService } from 'primeng/api';
189
// Module: ConfirmDialogModule
190
191
// Service Configuration
192
interface Confirmation {
193
message?: string;
194
key?: string;
195
icon?: string;
196
header?: string;
197
accept?: Function;
198
reject?: Function;
199
acceptLabel?: string;
200
rejectLabel?: string;
201
acceptIcon?: string;
202
rejectIcon?: string;
203
acceptVisible?: boolean;
204
rejectVisible?: boolean;
205
blockScroll?: boolean;
206
closeOnEscape?: boolean;
207
dismissableMask?: boolean;
208
defaultFocus?: string;
209
acceptButtonStyleClass?: string;
210
rejectButtonStyleClass?: string;
211
target?: EventTarget;
212
acceptEvent?: Event;
213
rejectEvent?: Event;
214
}
215
216
// Usage
217
@Component({
218
template: `
219
<p-toast></p-toast>
220
<p-confirmdialog></p-confirmdialog>
221
222
<!-- Multiple Confirm Dialogs -->
223
<p-confirmdialog key="positionDialog" [position]="position" [style]="{width: '50vw'}"></p-confirmdialog>
224
225
<div class="card flex flex-wrap gap-2 justify-content-center">
226
<p-button (onClick)="confirm1()" icon="pi pi-check" label="Confirm" size="small"></p-button>
227
<p-button (onClick)="confirm2()" icon="pi pi-times" label="Delete" severity="danger" size="small"></p-button>
228
<p-button (onClick)="confirmPosition('top')" icon="pi pi-arrow-up" label="Top" size="small" styleClass="p-button-help"></p-button>
229
</div>
230
`,
231
providers: [ConfirmationService]
232
})
233
export class ConfirmDialogComponent {
234
position: string = 'center';
235
236
constructor(private confirmationService: ConfirmationService, private messageService: MessageService) {}
237
238
confirm1() {
239
this.confirmationService.confirm({
240
message: 'Are you sure that you want to proceed?',
241
header: 'Confirmation',
242
icon: 'pi pi-exclamation-triangle',
243
accept: () => {
244
this.messageService.add({severity:'info', summary:'Confirmed', detail:'You have accepted'});
245
},
246
reject: (type: any) => {
247
switch(type) {
248
case ConfirmEventType.REJECT:
249
this.messageService.add({severity:'error', summary:'Rejected', detail:'You have rejected'});
250
break;
251
case ConfirmEventType.CANCEL:
252
this.messageService.add({severity:'warn', summary:'Cancelled', detail:'You have cancelled'});
253
break;
254
}
255
}
256
});
257
}
258
259
confirm2() {
260
this.confirmationService.confirm({
261
message: 'Do you want to delete this record?',
262
header: 'Delete Confirmation',
263
icon: 'pi pi-info-circle',
264
acceptButtonStyleClass: 'p-button-danger p-button-text',
265
rejectButtonStyleClass: 'p-button-text p-button-text',
266
acceptIcon: 'none',
267
rejectIcon: 'none',
268
accept: () => {
269
this.messageService.add({severity:'info', summary:'Confirmed', detail:'Record deleted'});
270
},
271
reject: () => {
272
this.messageService.add({severity:'error', summary:'Rejected', detail:'You have rejected'});
273
}
274
});
275
}
276
277
confirmPosition(position: string) {
278
this.position = position;
279
this.confirmationService.confirm({
280
key: 'positionDialog',
281
message: 'Do you want to delete this record?',
282
header: 'Delete Confirmation',
283
icon: 'pi pi-info-circle',
284
accept: () => {
285
this.messageService.add({severity:'info', summary:'Confirmed', detail:'Record deleted'});
286
},
287
reject: () => {
288
this.messageService.add({severity:'error', summary:'Rejected', detail:'You have rejected'});
289
}
290
});
291
}
292
}
293
```
294
295
### ConfirmPopup
296
297
Confirmation popup tooltip attached to target element.
298
299
```typescript { .api }
300
// Import
301
import { ConfirmPopup } from 'primeng/confirmpopup';
302
import { ConfirmationService } from 'primeng/api';
303
// Module: ConfirmPopupModule
304
305
// Usage
306
@Component({
307
template: `
308
<p-toast></p-toast>
309
<p-confirmpopup></p-confirmpopup>
310
311
<div class="card flex flex-wrap gap-2 justify-content-center">
312
<p-button (onClick)="confirm1($event)" icon="pi pi-check" label="Save" size="small"></p-button>
313
<p-button (onClick)="confirm2($event)" icon="pi pi-times" label="Delete" severity="danger" size="small"></p-button>
314
</div>
315
`,
316
providers: [ConfirmationService]
317
})
318
export class ConfirmPopupComponent {
319
constructor(private confirmationService: ConfirmationService, private messageService: MessageService) {}
320
321
confirm1(event: Event) {
322
this.confirmationService.confirm({
323
target: event.target as EventTarget,
324
message: 'Are you sure that you want to proceed?',
325
header: 'Confirmation',
326
icon: 'pi pi-exclamation-triangle',
327
acceptIcon: 'none',
328
rejectIcon: 'none',
329
rejectButtonStyleClass: 'p-button-text',
330
accept: () => {
331
this.messageService.add({severity:'info', summary:'Confirmed', detail:'You have accepted'});
332
},
333
reject: () => {
334
this.messageService.add({severity:'error', summary:'Rejected', detail:'You have rejected'});
335
}
336
});
337
}
338
339
confirm2(event: Event) {
340
this.confirmationService.confirm({
341
target: event.target as EventTarget,
342
message: 'Do you want to delete this record?',
343
header: 'Delete Confirmation',
344
icon: 'pi pi-info-circle',
345
acceptButtonStyleClass: 'p-button-danger p-button-text',
346
rejectButtonStyleClass: 'p-button-text p-button-text',
347
acceptIcon: 'none',
348
rejectIcon: 'none',
349
accept: () => {
350
this.messageService.add({severity:'info', summary:'Confirmed', detail:'Record deleted'});
351
},
352
reject: () => {
353
this.messageService.add({severity:'error', summary:'Rejected', detail:'You have rejected'});
354
}
355
});
356
}
357
}
358
```
359
360
### DynamicDialog
361
362
Programmatically created dialogs with component injection.
363
364
```typescript { .api }
365
// Import
366
import { DynamicDialogModule, DynamicDialogRef, DialogService } from 'primeng/dynamicdialog';
367
368
// Service Interface
369
interface DynamicDialogConfig {
370
data?: any;
371
header?: string;
372
footer?: string;
373
width?: string;
374
height?: string;
375
closeOnEscape?: boolean;
376
baseZIndex?: number;
377
autoZIndex?: boolean;
378
dismissableMask?: boolean;
379
rtl?: boolean;
380
style?: any;
381
contentStyle?: any;
382
styleClass?: string;
383
transitionOptions?: string;
384
closable?: boolean;
385
showHeader?: boolean;
386
modal?: boolean;
387
position?: string;
388
blockScroll?: boolean;
389
closeIcon?: string;
390
minimizeIcon?: string;
391
maximizeIcon?: string;
392
maximizable?: boolean;
393
keepInViewport?: boolean;
394
focusOnShow?: boolean;
395
focusTrap?: boolean;
396
resizable?: boolean;
397
draggable?: boolean;
398
maskStyleClass?: string;
399
}
400
401
// Dynamic Component
402
@Component({
403
template: `
404
<div class="flex align-items-center gap-3 mb-3">
405
<img src="assets/showcase/images/demo/avatar/{{data.image}}" alt="{{data.name}}" width="32" style="vertical-align: middle" />
406
<div>
407
<span class="font-bold">{{data.name}}</span>
408
<div>{{data.email}}</div>
409
</div>
410
</div>
411
412
<p>{{data.description}}</p>
413
414
<div class="flex justify-content-end gap-2">
415
<p-button label="Close" styleClass="p-button-text" (onClick)="closeDialog()"></p-button>
416
<p-button label="Save" (onClick)="saveUser()"></p-button>
417
</div>
418
`
419
})
420
export class UserDetailComponent {
421
constructor(
422
public ref: DynamicDialogRef,
423
public config: DynamicDialogConfig
424
) {}
425
426
get data() {
427
return this.config.data;
428
}
429
430
closeDialog() {
431
this.ref.close();
432
}
433
434
saveUser() {
435
this.ref.close(this.data);
436
}
437
}
438
439
// Parent Component
440
@Component({
441
template: `
442
<p-toast></p-toast>
443
444
<div class="card">
445
<p-table [value]="users" selectionMode="single" [(selection)]="selectedUser" dataKey="id"
446
(onRowSelect)="onRowSelect($event)" [metaKeySelection]="false">
447
<ng-template pTemplate="header">
448
<tr>
449
<th>Name</th>
450
<th>Image</th>
451
<th>Email</th>
452
</tr>
453
</ng-template>
454
<ng-template pTemplate="body" let-user>
455
<tr [pSelectableRow]="user">
456
<td>{{user.name}}</td>
457
<td><img src="assets/showcase/images/demo/avatar/{{user.image}}" alt="{{user.name}}" width="32" style="vertical-align: middle" /></td>
458
<td>{{user.email}}</td>
459
</tr>
460
</ng-template>
461
</p-table>
462
</div>
463
`,
464
providers: [DialogService]
465
})
466
export class DynamicDialogComponent {
467
users: User[] = [];
468
selectedUser: User = {};
469
ref: DynamicDialogRef | undefined;
470
471
constructor(
472
public dialogService: DialogService,
473
public messageService: MessageService
474
) {}
475
476
onRowSelect(event: any) {
477
this.ref = this.dialogService.open(UserDetailComponent, {
478
header: 'User Information',
479
width: '50%',
480
contentStyle: { overflow: 'auto' },
481
baseZIndex: 10000,
482
maximizable: true,
483
data: event.data
484
});
485
486
this.ref.onClose.subscribe((result: User) => {
487
if (result) {
488
this.messageService.add({severity:'info', summary:'User Selected', detail: result.name});
489
}
490
});
491
492
this.ref.onMaximize.subscribe((value) => {
493
this.messageService.add({severity:'info', summary:'Maximized', detail: `maximized: ${value.maximized}`});
494
});
495
}
496
497
ngOnDestroy() {
498
if (this.ref) {
499
this.ref.close();
500
}
501
}
502
}
503
```
504
505
## Drawer Component
506
507
### Drawer
508
509
Slide-out side panel for navigation or content.
510
511
```typescript { .api }
512
// Import
513
import { Drawer } from 'primeng/drawer';
514
// Module: DrawerModule
515
516
// Component Interface
517
interface DrawerProps {
518
visible?: boolean;
519
position?: 'left' | 'right' | 'top' | 'bottom' | 'full';
520
header?: string;
521
style?: any;
522
styleClass?: string;
523
maskStyleClass?: string;
524
contentStyle?: any;
525
contentStyleClass?: string;
526
modal?: boolean;
527
dismissible?: boolean;
528
showCloseIcon?: boolean;
529
closeIcon?: string;
530
autoZIndex?: boolean;
531
baseZIndex?: number;
532
transitionOptions?: string;
533
focusTrap?: boolean;
534
closeOnEscape?: boolean;
535
blockScroll?: boolean;
536
}
537
538
// Events
539
interface DrawerShowEvent {
540
originalEvent?: Event;
541
}
542
543
interface DrawerHideEvent {
544
originalEvent?: Event;
545
}
546
547
// Usage
548
@Component({
549
template: `
550
<!-- Left Drawer -->
551
<p-drawer header="Drawer" [(visible)]="visibleLeft" position="left" [style]="{width:'20rem'}">
552
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
553
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
554
</p-drawer>
555
556
<!-- Right Drawer -->
557
<p-drawer header="Drawer" [(visible)]="visibleRight" position="right" [style]="{width:'20rem'}">
558
<ng-template pTemplate="header">
559
<div class="flex align-items-center gap-2">
560
<p-avatar image="assets/showcase/images/demo/avatar/amyelsner.png" shape="circle"></p-avatar>
561
<span class="font-bold">Amy Elsner</span>
562
</div>
563
</ng-template>
564
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
565
<ng-template pTemplate="footer">
566
<div class="flex gap-2">
567
<p-button label="Save" (onClick)="visibleRight = false"></p-button>
568
<p-button label="Cancel" severity="secondary" (onClick)="visibleRight = false"></p-button>
569
</div>
570
</ng-template>
571
</p-drawer>
572
573
<!-- Top Drawer -->
574
<p-drawer header="Drawer" [(visible)]="visibleTop" position="top" [style]="{height:'20rem'}">
575
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
576
</p-drawer>
577
578
<!-- Bottom Drawer -->
579
<p-drawer header="Drawer" [(visible)]="visibleBottom" position="bottom" [style]="{height:'20rem'}">
580
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
581
</p-drawer>
582
583
<!-- Full Screen Drawer -->
584
<p-drawer header="Drawer" [(visible)]="visibleFull" position="full">
585
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
586
</p-drawer>
587
588
<div class="card flex justify-content-center gap-2 flex-wrap">
589
<p-button (onClick)="visibleLeft = true" icon="pi pi-arrow-right" label="Left"></p-button>
590
<p-button (onClick)="visibleRight = true" icon="pi pi-arrow-left" label="Right"></p-button>
591
<p-button (onClick)="visibleTop = true" icon="pi pi-arrow-down" label="Top"></p-button>
592
<p-button (onClick)="visibleBottom = true" icon="pi pi-arrow-up" label="Bottom"></p-button>
593
<p-button (onClick)="visibleFull = true" icon="pi pi-external-link" label="Full Screen"></p-button>
594
</div>
595
`
596
})
597
export class DrawerComponent {
598
visibleLeft: boolean = false;
599
visibleRight: boolean = false;
600
visibleTop: boolean = false;
601
visibleBottom: boolean = false;
602
visibleFull: boolean = false;
603
}
604
```
605
606
## Popup Components
607
608
### Popover
609
610
Floating content container positioned relative to target.
611
612
```typescript { .api }
613
// Import
614
import { Popover } from 'primeng/popover';
615
// Module: PopoverModule
616
617
// Component Interface
618
interface PopoverProps {
619
dismissable?: boolean;
620
style?: any;
621
styleClass?: string;
622
appendTo?: any;
623
autoZIndex?: boolean;
624
baseZIndex?: number;
625
showTransitionOptions?: string;
626
hideTransitionOptions?: string;
627
ariaLabel?: string;
628
ariaLabelledBy?: string;
629
}
630
631
// Usage
632
@Component({
633
template: `
634
<div class="card flex justify-content-center">
635
<p-button (onClick)="toggle($event)" icon="pi pi-share-alt" label="Share"></p-button>
636
637
<p-popover #op>
638
<div class="flex flex-column gap-3 w-25rem">
639
<div>
640
<span class="font-medium text-900 block mb-2">Share this document</span>
641
<p-inputtext placeholder="Email" class="w-full" size="small"></p-inputtext>
642
</div>
643
<div>
644
<div class="flex align-items-center gap-2 mb-2">
645
<label for="link" class="font-medium text-900">Share with link</label>
646
<p-inputswitch [(ngModel)]="linkActive"></p-inputswitch>
647
</div>
648
<p-inputtext [disabled]="!linkActive" placeholder="Role" class="w-full" size="small"></p-inputtext>
649
</div>
650
<div class="flex gap-2">
651
<p-button label="Save" size="small" (onClick)="op.hide()"></p-button>
652
<p-button label="Cancel" size="small" severity="secondary" (onClick)="op.hide()"></p-button>
653
</div>
654
</div>
655
</p-popover>
656
</div>
657
658
<!-- Custom Popover -->
659
<div class="card flex justify-content-center">
660
<img src="assets/showcase/images/demo/avatar/amyelsner.png"
661
(click)="toggleUserPopover($event)"
662
alt="user-avatar"
663
class="w-3rem h-3rem cursor-pointer border-circle shadow-4" />
664
665
<p-popover #userPopover>
666
<div class="flex flex-column">
667
<div class="flex align-items-center gap-2 mb-2">
668
<img src="assets/showcase/images/demo/avatar/amyelsner.png" alt="user-avatar" class="w-2rem h-2rem" />
669
<div>
670
<div class="font-medium">Amy Elsner</div>
671
<div class="text-sm text-color-secondary">Agent</div>
672
</div>
673
</div>
674
<ul class="list-none p-0 m-0">
675
<li class="border-bottom-1 surface-border p-2 hover:surface-hover cursor-pointer">Profile</li>
676
<li class="border-bottom-1 surface-border p-2 hover:surface-hover cursor-pointer">Settings</li>
677
<li class="p-2 hover:surface-hover cursor-pointer">Logout</li>
678
</ul>
679
</div>
680
</p-popover>
681
</div>
682
`
683
})
684
export class PopoverComponent {
685
linkActive: boolean = false;
686
687
toggle(event: Event) {
688
// Popover will be toggled via template reference
689
}
690
691
toggleUserPopover(event: Event) {
692
// Popover will be toggled via template reference
693
}
694
}
695
```
696
697
### Overlay
698
699
Generic overlay container for custom positioning.
700
701
```typescript { .api }
702
// Import
703
import { Overlay } from 'primeng/overlay';
704
// Module: OverlayModule
705
706
// Component Interface
707
interface OverlayProps {
708
visible?: boolean;
709
mode?: 'overlay' | 'modal';
710
style?: any;
711
styleClass?: string;
712
contentStyle?: any;
713
contentStyleClass?: string;
714
target?: any;
715
appendTo?: any;
716
autoZIndex?: boolean;
717
baseZIndex?: number;
718
showTransitionOptions?: string;
719
hideTransitionOptions?: string;
720
listener?: any;
721
responsive?: any;
722
options?: OverlayOptions;
723
}
724
725
interface OverlayOptions {
726
my?: string;
727
at?: string;
728
of?: any;
729
collision?: string;
730
}
731
732
// Usage
733
@Component({
734
template: `
735
<div class="card flex justify-content-center">
736
<p-button
737
type="button"
738
icon="pi pi-search"
739
(click)="toggle($event)"
740
aria-haspopup="true"
741
aria-controls="overlay_panel">
742
</p-button>
743
744
<p-overlay
745
[(visible)]="overlayVisible"
746
[target]="target"
747
[responsive]="responsiveOptions"
748
[showTransitionOptions]="'0.12s cubic-bezier(0, 0, 0.2, 1)'"
749
[hideTransitionOptions]="'0.12s cubic-bezier(0, 0, 0.2, 1)'"
750
(onAnimationStart)="onOverlayClick($event)">
751
<div class="flex flex-column gap-3 w-25rem">
752
<div>
753
<label for="search-input" class="font-medium text-900">Search Products</label>
754
<span class="p-input-icon-left w-full mt-2">
755
<i class="pi pi-search"></i>
756
<input pInputText id="search-input" type="text" placeholder="Search" class="w-full" />
757
</span>
758
</div>
759
<div>
760
<label for="category-select" class="font-medium text-900">Category</label>
761
<p-select
762
[options]="categories"
763
[(ngModel)]="selectedCategory"
764
optionLabel="name"
765
id="category-select"
766
placeholder="Select"
767
class="w-full mt-2">
768
</p-select>
769
</div>
770
<div class="flex gap-2">
771
<p-button label="Search" class="w-full"></p-button>
772
</div>
773
</div>
774
</p-overlay>
775
</div>
776
`
777
})
778
export class OverlayComponent {
779
overlayVisible: boolean = false;
780
target: any;
781
categories: any[] = [];
782
selectedCategory: any;
783
784
responsiveOptions: any = {
785
'960px': {
786
my: 'center top',
787
at: 'center bottom',
788
collision: 'flip'
789
},
790
'640px': {
791
my: 'center top',
792
at: 'center bottom',
793
collision: 'flip'
794
}
795
};
796
797
ngOnInit() {
798
this.categories = [
799
{ name: 'Electronics', code: 'ELE' },
800
{ name: 'Clothing', code: 'CLO' },
801
{ name: 'Books', code: 'BOO' }
802
];
803
}
804
805
toggle(event: Event) {
806
this.target = event.currentTarget;
807
this.overlayVisible = !this.overlayVisible;
808
}
809
810
onOverlayClick(event: any) {
811
if (event.toState === 'visible') {
812
console.log('Overlay shown');
813
}
814
}
815
}
816
```
817
818
## Toast Notifications
819
820
### Toast
821
822
Non-intrusive notification messages.
823
824
```typescript { .api }
825
// Import
826
import { Toast } from 'primeng/toast';
827
import { MessageService } from 'primeng/api';
828
// Module: ToastModule
829
830
// Component Interface
831
interface ToastProps {
832
key?: string;
833
autoZIndex?: boolean;
834
baseZIndex?: number;
835
style?: any;
836
styleClass?: string;
837
position?: 'top-right' | 'top-left' | 'bottom-left' | 'bottom-right' | 'top-center' | 'bottom-center' | 'center';
838
preventOpenDuplicates?: boolean;
839
preventDuplicates?: boolean;
840
showTransformOptions?: string;
841
hideTransformOptions?: string;
842
showTransitionOptions?: string;
843
hideTransitionOptions?: string;
844
breakpoints?: any;
845
}
846
847
// Message Interface
848
interface Message {
849
severity?: 'success' | 'info' | 'warn' | 'error' | 'custom';
850
summary?: string;
851
detail?: string;
852
id?: any;
853
key?: string;
854
life?: number;
855
sticky?: boolean;
856
closable?: boolean;
857
data?: any;
858
icon?: string;
859
contentStyleClass?: string;
860
styleClass?: string;
861
}
862
863
// Usage
864
@Component({
865
template: `
866
<p-toast></p-toast>
867
<p-toast position="top-left" key="tl"></p-toast>
868
<p-toast position="bottom-center" key="bc"></p-toast>
869
870
<div class="card flex flex-wrap gap-2 justify-content-center">
871
<p-button (onClick)="showSuccess()" label="Success" severity="success"></p-button>
872
<p-button (onClick)="showInfo()" label="Info" severity="info"></p-button>
873
<p-button (onClick)="showWarn()" label="Warn" severity="warning"></p-button>
874
<p-button (onClick)="showError()" label="Error" severity="danger"></p-button>
875
<p-button (onClick)="showTopLeft()" label="Top Left" styleClass="p-button-help"></p-button>
876
<p-button (onClick)="showBottomCenter()" label="Bottom" styleClass="p-button-help"></p-button>
877
<p-button (onClick)="showMultiple()" label="Multiple" severity="secondary"></p-button>
878
<p-button (onClick)="showSticky()" label="Sticky"></p-button>
879
<p-button (onClick)="showConfirm()" label="Confirm" severity="help"></p-button>
880
<p-button (onClick)="clear()" label="Clear" class="p-button-secondary"></p-button>
881
</div>
882
`,
883
providers: [MessageService]
884
})
885
export class ToastComponent {
886
constructor(private messageService: MessageService) {}
887
888
showSuccess() {
889
this.messageService.add({severity:'success', summary: 'Success', detail: 'Message Content'});
890
}
891
892
showInfo() {
893
this.messageService.add({severity:'info', summary: 'Info', detail: 'Message Content'});
894
}
895
896
showWarn() {
897
this.messageService.add({severity:'warn', summary: 'Warn', detail: 'Message Content'});
898
}
899
900
showError() {
901
this.messageService.add({severity:'error', summary: 'Error', detail: 'Message Content'});
902
}
903
904
showTopLeft() {
905
this.messageService.add({key: 'tl', severity:'info', summary: 'Info', detail: 'Message Content'});
906
}
907
908
showBottomCenter() {
909
this.messageService.add({key: 'bc', severity:'success', summary: 'Success', detail: 'Message Content'});
910
}
911
912
showSticky() {
913
this.messageService.add({severity:'info', summary: 'Sticky', detail: 'Message Content', sticky: true});
914
}
915
916
showMultiple() {
917
this.messageService.addAll([
918
{severity:'info', summary: 'Message 1', detail: 'Message Content'},
919
{severity:'info', summary: 'Message 2', detail: 'Message Content'},
920
{severity:'info', summary: 'Message 3', detail: 'Message Content'}
921
]);
922
}
923
924
showConfirm() {
925
this.messageService.clear();
926
this.messageService.add({key: 'c', sticky: true, severity:'warn', summary:'Are you sure?', detail:'Confirm to proceed'});
927
}
928
929
onConfirm() {
930
this.messageService.clear('c');
931
this.messageService.add({severity:'info', summary:'Confirmed', detail:'You have accepted'});
932
}
933
934
onReject() {
935
this.messageService.clear('c');
936
this.messageService.add({severity:'error', summary:'Rejected', detail:'You have rejected'});
937
}
938
939
clear() {
940
this.messageService.clear();
941
}
942
}
943
```
944
945
## Overlay Service
946
947
The OverlayService provides global overlay management:
948
949
```typescript { .api }
950
// Service Interface
951
class OverlayService {
952
onShow: Subject<any>;
953
onHide: Subject<any>;
954
}
955
956
// Usage
957
@Component({})
958
export class CustomComponent {
959
constructor(private overlayService: OverlayService) {
960
this.overlayService.onShow.subscribe(() => {
961
console.log('Overlay shown');
962
});
963
964
this.overlayService.onHide.subscribe(() => {
965
console.log('Overlay hidden');
966
});
967
}
968
}
969
```
970
971
## Z-Index Management
972
973
PrimeNG automatically manages z-index layering for overlays:
974
975
```typescript
976
// Global Configuration
977
providePrimeNG({
978
zIndex: {
979
modal: 1100, // Dialog, Drawer
980
overlay: 1000, // Popover, Overlay
981
menu: 1000, // Context Menu, Menu
982
tooltip: 1100 // Tooltip
983
}
984
})
985
```
986
987
## Accessibility Features
988
989
All overlay components include comprehensive accessibility support:
990
991
- **Focus management** - Automatic focus trapping and restoration
992
- **ARIA attributes** - Proper roles, labels, and states
993
- **Keyboard navigation** - ESC to close, Tab navigation
994
- **Screen reader support** - Announcements and descriptions
995
- **Modal behavior** - Background interaction blocking