Alert Dialog

Ask the user to confirm or cancel an important action in a centered panel that only closes when they choose.

Installation

npx @blotch/dolan add alert-dialog
import {
  UiAlertDialog,
  UiAlertDialogHeader,
  UiAlertDialogTitle,
  UiAlertDialogDescription,
  UiAlertDialogFooter,
} from '../components/ui/alert-dialog';

Usage

import { Component, signal } from '@angular/core';
import {
  UiAlertDialog,
  UiAlertDialogHeader,
  UiAlertDialogTitle,
  UiAlertDialogDescription,
  UiAlertDialogFooter,
} from '../components/ui/alert-dialog';
import { UiButton } from '../components/ui/button';

@Component({
  selector: 'app-delete-account',
  imports: [
    UiAlertDialog,
    UiAlertDialogHeader,
    UiAlertDialogTitle,
    UiAlertDialogDescription,
    UiAlertDialogFooter,
    UiButton,
  ],
  template: `
    <ui-button variant="destructive" (pressed)="open.set(true)">
      Delete account
    </ui-button>

    <ui-alert-dialog [(open)]="open">
      <ui-alert-dialog-header>
        <ui-alert-dialog-title>Are you sure?</ui-alert-dialog-title>
        <ui-alert-dialog-description>
          This action can't be undone.
        </ui-alert-dialog-description>
      </ui-alert-dialog-header>
      <ui-alert-dialog-footer>
        <ui-button variant="outline" (pressed)="open.set(false)">
          Cancel
        </ui-button>
        <ui-button variant="destructive" (pressed)="confirm()">
          Delete
        </ui-button>
      </ui-alert-dialog-footer>
    </ui-alert-dialog>
  `,
})
export class DeleteAccount {
  protected readonly open = signal(false);

  protected confirm(): void {
    // Delete the account here.
    this.open.set(false);
  }
}
  • Unlike Dialog, tapping the backdrop does nothing. Your buttons are the only way to close it, so always include one that cancels.
  • [(open)] two-way binds a signal. Set it to true to open the dialog and false to close it.
  • The backdrop fades in and the panel scales up. Closing plays the reverse.
  • The dialog draws in an <overlay>, so it covers the whole screen wherever it sits in your template.
  • <ui-alert-dialog-title> and <ui-alert-dialog-description> render <text>, so put plain text in them. The footer lays out its buttons in a row, aligned right.

Run code after it closes

closed emits once the close animation has finished, about 270ms after open turns false. It fires from a timer, outside any tap handler, so it's a safe place to navigate. To navigate straight from a button instead, wrap the navigation in setTimeout (see the setTimeout rule).

<ui-alert-dialog [(open)]="open" (closed)="onClosed()">…</ui-alert-dialog>

Panel width

class goes on the panel, which is w-4/5 wide by default.

<ui-alert-dialog [(open)]="open" class="w-11/12">…</ui-alert-dialog>

API

UiAlertDialog

InputTypeDefaultDescription
openbooleanfalseWhether the dialog is shown. Supports [(open)].
classstring''Extra Tailwind classes for the panel.
OutputTypeDescription
openChangebooleanPart of [(open)]. The alert dialog never closes itself, so it doesn't emit.
closedvoidEmits after the close animation finishes.

All sub-components (UiAlertDialogHeader, UiAlertDialogTitle, UiAlertDialogDescription, UiAlertDialogFooter) accept class.