alert dialog

A modal dialog that interrupts the user with important content and expects a response.

PreviousNext
import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
import { ZardAlertDialogService } from '@/shared/components/alert-dialog/alert-dialog.service';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTabsImports } from '@/shared/components/tabs/tabs.imports';

@Component({
  selector: 'z-demo-alert-dialog-preview',
  imports: [ZardAlertDialogImports, ZardButtonComponent, ZardTabsImports],
  template: `
    <z-tab-group>
      <z-tab label="Template">
        <button type="button" z-button zType="outline" (click)="visible.set(true)">Show Dialog</button>

        <z-alert-dialog [(zVisible)]="visible">
          <z-alert-dialog-header>
            <z-alert-dialog-title>Are you absolutely sure?</z-alert-dialog-title>
            <z-alert-dialog-description>
              This action cannot be undone. This will permanently delete your account from our servers.
            </z-alert-dialog-description>
          </z-alert-dialog-header>
          <z-alert-dialog-footer>
            <button type="button" z-button zType="outline" z-alert-dialog-close>Cancel</button>
            <button type="button" z-button (click)="visible.set(false)">Continue</button>
          </z-alert-dialog-footer>
        </z-alert-dialog>
      </z-tab>

      <z-tab label="Service">
        <button type="button" z-button zType="outline" (click)="open()">Show Dialog</button>
      </z-tab>
    </z-tab-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoAlertDialogPreviewComponent {
  private readonly alertDialogService = inject(ZardAlertDialogService);

  readonly visible = signal(false);

  open() {
    this.alertDialogService.create({
      zTitle: 'Are you absolutely sure?',
      zDescription: 'This action cannot be undone. This will permanently delete your account from our servers.',
      zOkText: 'Continue',
      zCancelText: 'Cancel',
    });
  }
}

Installation

Copy
npx zard-cli@latest add alert-dialog

Usage

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
Copy
<button type="button" z-button zType="outline" (click)="visible.set(true)">Show Dialog</button>

<z-alert-dialog [(zVisible)]="visible">
  <z-alert-dialog-header>
    <z-alert-dialog-title>Are you absolutely sure?</z-alert-dialog-title>
    <z-alert-dialog-description>
      This action cannot be undone. This will permanently delete your account and remove your data from our servers.
    </z-alert-dialog-description>
  </z-alert-dialog-header>
  <z-alert-dialog-footer>
    <button type="button" z-button zType="outline" z-alert-dialog-close>Cancel</button>
    <button type="button" z-button (click)="visible.set(false)">Continue</button>
  </z-alert-dialog-footer>
</z-alert-dialog>
Copy

Composition

Use the following composition to build a alert-dialog:

z-alert-dialog
├── z-alert-dialog-header
│   ├── z-alert-dialog-media
│   ├── z-alert-dialog-title
│   └── z-alert-dialog-description
└── z-alert-dialog-footer
    └── [z-alert-dialog-close]
Copy

Examples

basic

The minimal alert dialog: a title, a description and the cancel/continue buttons. In the template the buttons are yours; [z-alert-dialog-close] closes without a handler.
import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
import { ZardAlertDialogService } from '@/shared/components/alert-dialog/alert-dialog.service';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTabsImports } from '@/shared/components/tabs/tabs.imports';

@Component({
  selector: 'z-demo-alert-dialog-basic',
  imports: [ZardAlertDialogImports, ZardButtonComponent, ZardTabsImports],
  template: `
    <z-tab-group>
      <z-tab label="Template">
        <button type="button" z-button zType="outline" (click)="visible.set(true)">Show Dialog</button>

        <z-alert-dialog [(zVisible)]="visible">
          <z-alert-dialog-header>
            <z-alert-dialog-title>Are you absolutely sure?</z-alert-dialog-title>
            <z-alert-dialog-description>
              This action cannot be undone. This will permanently delete your account and remove your data from our
              servers.
            </z-alert-dialog-description>
          </z-alert-dialog-header>
          <z-alert-dialog-footer>
            <button type="button" z-button zType="outline" z-alert-dialog-close>Cancel</button>
            <button type="button" z-button (click)="visible.set(false)">Continue</button>
          </z-alert-dialog-footer>
        </z-alert-dialog>
      </z-tab>

      <z-tab label="Service">
        <button type="button" z-button zType="outline" (click)="open()">Show Dialog</button>
      </z-tab>
    </z-tab-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoAlertDialogBasicComponent {
  private readonly alertDialogService = inject(ZardAlertDialogService);

  readonly visible = signal(false);

  open() {
    this.alertDialogService.create({
      zTitle: 'Are you absolutely sure?',
      zDescription:
        'This action cannot be undone. This will permanently delete your account and remove your data from our servers.',
      zOkText: 'Continue',
      zCancelText: 'Cancel',
    });
  }
}

small

Use zSize="sm", as an input or an option, to make the alert dialog smaller.
import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
import { ZardAlertDialogService } from '@/shared/components/alert-dialog/alert-dialog.service';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTabsImports } from '@/shared/components/tabs/tabs.imports';

@Component({
  selector: 'z-demo-alert-dialog-small',
  imports: [ZardAlertDialogImports, ZardButtonComponent, ZardTabsImports],
  template: `
    <z-tab-group>
      <z-tab label="Template">
        <button type="button" z-button zType="outline" (click)="visible.set(true)">Show Dialog</button>

        <z-alert-dialog [(zVisible)]="visible" zSize="sm">
          <z-alert-dialog-header>
            <z-alert-dialog-title>Allow accessory to connect?</z-alert-dialog-title>
            <z-alert-dialog-description>
              Do you want to allow the USB accessory to connect to this device?
            </z-alert-dialog-description>
          </z-alert-dialog-header>
          <z-alert-dialog-footer>
            <button type="button" z-button zType="outline" z-alert-dialog-close>Don't allow</button>
            <button type="button" z-button (click)="visible.set(false)">Allow</button>
          </z-alert-dialog-footer>
        </z-alert-dialog>
      </z-tab>

      <z-tab label="Service">
        <button type="button" z-button zType="outline" (click)="open()">Show Dialog</button>
      </z-tab>
    </z-tab-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoAlertDialogSmallComponent {
  private readonly alertDialogService = inject(ZardAlertDialogService);

  readonly visible = signal(false);

  open() {
    this.alertDialogService.create({
      zSize: 'sm',
      zTitle: 'Allow accessory to connect?',
      zDescription: 'Do you want to allow the USB accessory to connect to this device?',
      zOkText: 'Allow',
      zCancelText: "Don't allow",
    });
  }
}

media

Add a media element such as an icon above the title: z-alert-dialog-media in the template, or a <ng-template> passed via zMedia to the service.
import { ChangeDetectionStrategy, Component, inject, signal, type TemplateRef } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideCircleFadingPlus } from '@ng-icons/lucide';

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
import { ZardAlertDialogService } from '@/shared/components/alert-dialog/alert-dialog.service';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTabsImports } from '@/shared/components/tabs/tabs.imports';

@Component({
  selector: 'z-demo-alert-dialog-media',
  imports: [ZardAlertDialogImports, ZardButtonComponent, ZardTabsImports, NgIcon],
  template: `
    <z-tab-group>
      <z-tab label="Template">
        <button type="button" z-button zType="outline" (click)="visible.set(true)">Share Project</button>

        <z-alert-dialog [(zVisible)]="visible">
          <z-alert-dialog-header>
            <z-alert-dialog-media>
              <ng-icon name="lucideCircleFadingPlus" />
            </z-alert-dialog-media>
            <z-alert-dialog-title>Share this project?</z-alert-dialog-title>
            <z-alert-dialog-description>
              Anyone with the link will be able to view and edit this project.
            </z-alert-dialog-description>
          </z-alert-dialog-header>
          <z-alert-dialog-footer>
            <button type="button" z-button zType="outline" z-alert-dialog-close>Cancel</button>
            <button type="button" z-button (click)="visible.set(false)">Share</button>
          </z-alert-dialog-footer>
        </z-alert-dialog>
      </z-tab>

      <z-tab label="Service">
        <ng-template #mediaIcon>
          <ng-icon name="lucideCircleFadingPlus" />
        </ng-template>
        <button type="button" z-button zType="outline" (click)="open(mediaIcon)">Share Project</button>
      </z-tab>
    </z-tab-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [provideIcons({ lucideCircleFadingPlus })],
})
export class ZardDemoAlertDialogMediaComponent {
  private readonly alertDialogService = inject(ZardAlertDialogService);

  readonly visible = signal(false);

  open(media: TemplateRef<void>) {
    this.alertDialogService.create({
      zMedia: media,
      zTitle: 'Share this project?',
      zDescription: 'Anyone with the link will be able to view and edit this project.',
      zOkText: 'Share',
      zCancelText: 'Cancel',
    });
  }
}

small with media

Combine zSize="sm" with the media slot to add a media element to the smaller alert dialog.
import { ChangeDetectionStrategy, Component, inject, signal, type TemplateRef } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideBluetooth } from '@ng-icons/lucide';

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
import { ZardAlertDialogService } from '@/shared/components/alert-dialog/alert-dialog.service';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTabsImports } from '@/shared/components/tabs/tabs.imports';

@Component({
  selector: 'z-demo-alert-dialog-small-with-media',
  imports: [ZardAlertDialogImports, ZardButtonComponent, ZardTabsImports, NgIcon],
  template: `
    <z-tab-group>
      <z-tab label="Template">
        <button type="button" z-button zType="outline" (click)="visible.set(true)">Show Dialog</button>

        <z-alert-dialog [(zVisible)]="visible" zSize="sm">
          <z-alert-dialog-header>
            <z-alert-dialog-media>
              <ng-icon name="lucideBluetooth" />
            </z-alert-dialog-media>
            <z-alert-dialog-title>Allow accessory to connect?</z-alert-dialog-title>
            <z-alert-dialog-description>
              Do you want to allow the USB accessory to connect to this device?
            </z-alert-dialog-description>
          </z-alert-dialog-header>
          <z-alert-dialog-footer>
            <button type="button" z-button zType="outline" z-alert-dialog-close>Don't allow</button>
            <button type="button" z-button (click)="visible.set(false)">Allow</button>
          </z-alert-dialog-footer>
        </z-alert-dialog>
      </z-tab>

      <z-tab label="Service">
        <ng-template #mediaIcon>
          <ng-icon name="lucideBluetooth" />
        </ng-template>
        <button type="button" z-button zType="outline" (click)="open(mediaIcon)">Show Dialog</button>
      </z-tab>
    </z-tab-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [provideIcons({ lucideBluetooth })],
})
export class ZardDemoAlertDialogSmallWithMediaComponent {
  private readonly alertDialogService = inject(ZardAlertDialogService);

  readonly visible = signal(false);

  open(media: TemplateRef<void>) {
    this.alertDialogService.create({
      zSize: 'sm',
      zMedia: media,
      zTitle: 'Allow accessory to connect?',
      zDescription: 'Do you want to allow the USB accessory to connect to this device?',
      zOkText: 'Allow',
      zCancelText: "Don't allow",
    });
  }
}

destructive

A destructive action: tint the media slot (class on z-alert-dialog-media, or zMediaClass) and make the confirm button destructive (zType="destructive", or zOkDestructive: true).
import { ChangeDetectionStrategy, Component, inject, signal, type TemplateRef } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrash2 } from '@ng-icons/lucide';

import { ZardAlertDialogImports } from '@/shared/components/alert-dialog/alert-dialog.imports';
import { ZardAlertDialogService } from '@/shared/components/alert-dialog/alert-dialog.service';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardTabsImports } from '@/shared/components/tabs/tabs.imports';

@Component({
  selector: 'z-demo-alert-dialog-destructive',
  imports: [ZardAlertDialogImports, ZardButtonComponent, ZardTabsImports, NgIcon],
  template: `
    <z-tab-group>
      <z-tab label="Template">
        <button type="button" z-button zType="destructive" (click)="visible.set(true)">Delete Chat</button>

        <z-alert-dialog [(zVisible)]="visible" zSize="sm">
          <z-alert-dialog-header>
            <z-alert-dialog-media class="bg-destructive/10 text-destructive dark:bg-destructive/20">
              <ng-icon name="lucideTrash2" />
            </z-alert-dialog-media>
            <z-alert-dialog-title>Delete chat?</z-alert-dialog-title>
            <z-alert-dialog-description>
              This will permanently delete this chat conversation. View
              <a href="#">Settings</a>
              delete any memories saved during this chat.
            </z-alert-dialog-description>
          </z-alert-dialog-header>
          <z-alert-dialog-footer>
            <button type="button" z-button zType="outline" z-alert-dialog-close>Cancel</button>
            <button type="button" z-button zType="destructive" (click)="visible.set(false)">Delete</button>
          </z-alert-dialog-footer>
        </z-alert-dialog>
      </z-tab>

      <z-tab label="Service">
        <ng-template #mediaIcon>
          <ng-icon name="lucideTrash2" />
        </ng-template>
        <button type="button" z-button zType="destructive" (click)="open(mediaIcon)">Delete Chat</button>
      </z-tab>
    </z-tab-group>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [provideIcons({ lucideTrash2 })],
})
export class ZardDemoAlertDialogDestructiveComponent {
  private readonly alertDialogService = inject(ZardAlertDialogService);

  readonly visible = signal(false);

  open(media: TemplateRef<void>) {
    this.alertDialogService.create({
      zSize: 'sm',
      zMedia: media,
      zMediaClass: 'bg-destructive/10 text-destructive dark:bg-destructive/20',
      zTitle: 'Delete chat?',
      zDescription:
        'This will permanently delete this chat conversation. View <a href="#">Settings</a> delete any memories saved during this chat.',
      zOkText: 'Delete',
      zCancelText: 'Cancel',
      zOkDestructive: true,
    });
  }
}

API Reference

z-alert-dialogComponent

Root of a declarative alert dialog. Holds the open state and projects its content into the panel (`role="alertdialog"`), which exposes `data-size` and `data-state` (`open` | `closed`) while the enter and leave transitions run.

PropertyDescriptionTypeDefault
[zVisible] Open state, two-way bound boolean false
[zSize] Visual size. `default` widens on `sm+` and lays the media next to the title; `sm` keeps a compact, centered layout 'default' | 'sm' 'default'
[zWidth] Custom width (e.g., '400px', '50%') string -
[zMaskClosable] Whether clicking outside closes the alert dialog. Off by default: the user has to decide boolean false
[zDuration] How long the enter and leave transitions run, in ms number 100
[class] Custom CSS classes applied to the panel ClassValue -
(zAfterOpen) Emitted once the alert dialog is attached EventEmitter<void> -
(zAfterClose) Emitted once the exit transition has finished EventEmitter<void> -

z-alert-dialog-headerComponent

Layout slot for the top of an alert dialog: `z-alert-dialog-media`, `z-alert-dialog-title` and `z-alert-dialog-description`.

PropertyDescriptionTypeDefault
[class] Custom CSS classes to apply ClassValue -

z-alert-dialog-mediaComponent

Media slot above the title, usually an icon. The header lays it next to the title on `default` size.

PropertyDescriptionTypeDefault
[class] Custom CSS classes to apply (e.g. tinted backgrounds for destructive) ClassValue -

z-alert-dialog-titleComponent

Accessible name of the alert dialog. Wired to `aria-labelledby` automatically.

PropertyDescriptionTypeDefault
[zTitle] Title text or template, when not projecting content string | TemplateRef<void> -
[class] Custom CSS classes to apply ClassValue -

z-alert-dialog-descriptionComponent

Supporting text. Wired to `aria-describedby` automatically.

PropertyDescriptionTypeDefault
[zDescription] Description text or template, when not projecting content string | TemplateRef<void> -
[class] Custom CSS classes to apply ClassValue -

z-alert-dialog-footerComponent

Layout slot for the action buttons.

PropertyDescriptionTypeDefault
[class] Custom CSS classes to apply ClassValue -

[z-alert-dialog-close]Component

Closes the alert dialog it is projected into. Works for declarative and service-opened alert dialogs alike.

ZardAlertDialogServiceComponent

Opens the same alert dialog from code. `create()`, `confirm()`, `warning()` and `info()` take the options below and return a `ZardAlertDialogRef`.

PropertyDescriptionTypeDefault
[zTitle] Dialog title text or template string | TemplateRef<void> -
[zDescription] Dialog description/body text string -
[zMedia] Template rendered as a media slot above the title (e.g. an icon) TemplateRef<void> -
[zMediaClass] Extra classes applied to the media slot wrapper (e.g. tinted backgrounds for destructive) ClassValue -
[zData] Data to pass to custom content components object -
[zOkText] OK button text, null to hide button string | null 'Continue'
[zCancelText] Cancel button text, null to hide button string | null 'Cancel'
[zOkDestructive] Whether OK button should have destructive styling boolean false
[zOkDisabled] Whether OK button should be disabled boolean false
[zMaskClosable] Whether clicking outside closes the dialog boolean false
[zClosable] Whether dialog can be closed boolean true
[zSize] Visual size of the dialog. `default` is wider on `sm+` breakpoints; `sm` keeps a compact width 'default' | 'sm' 'default'
[zWidth] Custom width (e.g., '400px', '50%') string -
[zCustomClasses] Additional CSS classes to apply ClassValue -
[zDuration] Animation duration (ms) used when closing. Matches the CSS transition number 100
[zOnOk] OK button click handler EventEmitter<T> | OnClickCallback<T> -
[zOnCancel] Cancel button click handler EventEmitter<T> | OnClickCallback<T> -
[zViewContainerRef] View container for rendering custom content ViewContainerRef -
github iconwhatsapp icondiscord iconX icon

Made with ❤ in Brazil. Open source and available on GitHub .