Advanced Components

Dialog

A modal window that appears on top of the page content. Useful for confirmations, forms, informational messages, or any flow that requires focused user attention.

Example

A simple dialog with a title, description, and action buttons.

Basic dialog
<div buiDialog>
<button matButton buiDialogTrigger>Edit Profile</button>
<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>
<div buiDialogHeader>
<h2 buiDialogTitle>Edit Profile</h2>
<p buiDialogDescription>
Make changes to your profile information.
Click save when you're done.
</p>
</div>
<div buiDialogBody>...</div>
<div buiDialogFooter>
<button matButton buiDialogClose>Cancel</button>
<button matButton buiDialogClose class="primary">
Save changes
</button>
</div>
</div>
</ng-template>
</div>

Structure

The dialog is fully directive-based. You compose it by applying attribute directives to standard HTML elements.

<div buiDialog>
<button matButton buiDialogTrigger>Open</button>

<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>
<div buiDialogHeader>
<h2 buiDialogTitle>Title</h2>
<p buiDialogDescription>Description</p>
</div>

<div buiDialogBody>
Scrollable content goes here
</div>

<div buiDialogFooter>
<button matButton buiDialogClose>Close</button>
</div>
</div>
</ng-template>
</div>

The building blocks are:

DirectiveDescription
buiDialogRoot container. Manages open state and the CDK dialog.
buiDialogTriggerOpens the dialog when clicked.
buiDialogPortal Wraps the content that is rendered inside a CDK dialog overlay.
buiDialogBackdropSemi-transparent backdrop behind the dialog. Optional.
buiDialogContentThe dialog panel itself.
buiDialogHeaderHeader area containing title and description.
buiDialogTitleTitle text inside the header.
buiDialogDescriptionDescription text inside the header. Optional.
buiDialogBodyScrollable main content area.
buiDialogFooterFooter area for action buttons.
buiDialogCloseCloses the dialog when clicked.

buiDialog

The root directive. Apply it to any element to create a dialog instance. It manages the open state, handles keyboard and backdrop dismissal, and renders the content inside a CDK dialog.

<!-- Default -->
<div buiDialog>...</div>

<!-- Alert dialog (no backdrop/Escape dismissal) -->
<div buiDialog disableClose role="alertdialog">...</div>

<!-- Two-way open binding -->
<div buiDialog [(open)]="isOpen">...</div>
PropTypeDefaultDescription
openmodel<boolean>falseTwo-way binding for the open state.
role'dialog' | 'alertdialog''dialog' ARIA role for the dialog. Use 'alertdialog' for confirmations that require explicit user action.
disableClosebooleanfalse Prevents closing via backdrop click or Escape key.
autoFocus'dialog' | 'first-tabbable' | 'first-heading' | string | undefined'first-tabbable' Configures where focus goes when the dialog opens.
restoreFocusboolean | string | HTMLElementtrue Configures where focus returns when the dialog closes.
(opened)voidEmits when the dialog opens.
(closed)void Emits after the dialog closes and its exit animation completes.

Trigger

Apply buiDialogTrigger to a button or any clickable element. It automatically sets aria-expanded, aria-controls, and keyboard support (Enter / Space).

<button matButton buiDialogTrigger>Open Dialog</button>

Portal

The buiDialogPortal directive goes on an ng-template. Its content is projected into a CDK dialog overlay when the dialog opens.

<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>
<!-- header, body, footer -->
</div>
</ng-template>

Backdrop

Add buiDialogBackdrop inside the portal to render a semi-transparent overlay behind the dialog. It is optional, omitting it gives you a dialog without a dimmed background.

Content

The buiDialogContent directive marks the dialog panel. It handles positioning, entry/exit animations, and nested dialog scaling. Place header, body, and footer directives inside it.

Header, Title & Description

The header groups the title and description at the top of the dialog. buiDialogTitle automatically connects to aria-labelledby on the dialog, and buiDialogDescription (optional) connects to aria-describedby.

<div buiDialogHeader>
<h2 buiDialogTitle>Title</h2>
<p buiDialogDescription>Optional description text</p>
</div>

Body

The scrollable main content area. It fills the available space between the header and footer. Use it when the dialog has more content than the title, description, and actions.

Footer

The footer area for action buttons. It aligns buttons to the end with appropriate spacing. Typically holds Cancel and Confirm buttons.

<div buiDialogFooter>
<button matButton buiDialogClose>Cancel</button>
<button matButton buiDialogClose class="primary">Confirm</button>
</div>

Close

Apply buiDialogClose to any element inside the portal. It closes the dialog when clicked. Attach your own (click) handler separately for additional logic.

<button matButton buiDialogClose (click)="onSave()">
Save & Close
</button>

Programmatic control

You can control the dialog without a trigger. Use the open model for two-way binding, or grab a template reference via #ref="buiDialog" and call open(), close(), or toggle().

<!-- Two-way binding -->
<div buiDialog [(open)]="isDialogOpen">
<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>...</div>
</ng-template>
</div>

<button matButton (click)="isDialogOpen = true">Open</button>

<!-- Template reference -->
<div buiDialog #myDialog="buiDialog">
<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>...</div>
</ng-template>
</div>

<button matButton (click)="myDialog.open()">Open</button>
<button matButton (click)="myDialog.close()">Close</button>
<button matButton (click)="myDialog.toggle()">Toggle</button>

Alert dialog

To create an alert dialog, a confirmation that requires explicit user action, add disableClose and role="alertdialog". This prevents dismissal via backdrop click or the Escape key and sets the correct ARIA role for assistive technologies.

Delete confirmation
<div buiDialog disableClose role="alertdialog">
<button matButton buiDialogTrigger>Delete Account</button>
<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>
<div buiDialogHeader>
<h2 buiDialogTitle>Are you sure?</h2>
<p buiDialogDescription>
This action cannot be undone. This will permanently
delete your account and remove all associated data
from our servers.
</p>
</div>
<div buiDialogFooter>
<button matButton buiDialogClose>Cancel</button>
<button matButton buiDialogClose class="primary destructive">
Delete
</button>
</div>
</div>
</ng-template>
</div>

Nested dialogs

Dialogs can be nested inside each other. Place a child buiDialog inside the parent's portal content and open it programmatically. The parent dialog automatically scales down and shifts when a child dialog opens, creating a clear visual hierarchy.

Two-step delete confirmation
<div buiDialog disableClose #parentDialog="buiDialog">
<button matButton buiDialogTrigger class="primary destructive">
Delete item
</button>
<ng-template buiDialogPortal>
<div buiDialogBackdrop></div>
<div buiDialogContent>
<div buiDialogHeader>
<h2 buiDialogTitle>
Are you sure you want to delete this item?
</h2>
<p buiDialogDescription>
This action cannot be undone. This will permanently
delete the item from our servers.
</p>
</div>
<div buiDialogFooter>
<button matButton buiDialogClose>Cancel</button>
<button
matButton
class="primary destructive"
(click)="confirmDialog.open()"
>
Delete
</button>
</div>
</div>
</ng-template>

<!-- Nested confirmation dialog -->
<div buiDialog disableClose #confirmDialog="buiDialog">
<ng-template buiDialogPortal>
<div buiDialogContent>
<div buiDialogHeader>
<p buiDialogDescription>
Are you absolutely sure? This will permanently
delete the item and all of its data. This action
cannot be undone.
</p>
</div>
<div buiDialogFooter>
<button
matButton
buiDialogClose
(click)="parentDialog.close()"
>
Cancel
</button>
<button
matButton
buiDialogClose
class="primary destructive"
(click)="parentDialog.close()"
>
Yes, delete it!
</button>
</div>
</div>
</ng-template>
</div>
</div>