TeqBench

TeqBench Material DialogsMaterial Dialogs

Components v2.0.3

An opinionated Angular modal dialog service built on Angular Material's MatDialog with severity-leveled methods (success / error / warning / information / help / default), dialog-specific UX patterns (confirm / input), pluggable severity and close icons, and rich footer controls.

npm install @teqbench/tbx-mat-dialogs

@teqbench/tbx-mat-dialogs provides modal dialogs for Angular applications. It complements small transient notifications and persistent banners with a heavier surface for focused interactions: long copy, multi-step input, complex confirmation flows, and arbitrary projected content. Dialogs render via Angular Material's MatDialog, which manages overlay, backdrop, focus trap, and modal semantics.

TbxMatDialogService exposes nine opinionated methods. Six mirror the severity-leveled surface of tbx-mat-banners and tbx-mat-notificationssuccess, error, warning, information, help, and default. Two are dialog-specific UX patterns layered on top of severity — confirm (Yes/No) and input (form content with OK/Cancel). The ninth, show, takes a full configuration for cases where the opinionated methods do not fit. All methods return a Promise<TbxMatDialogResult<T, F>> so consumers can await the user's choice with no subscription management.

Severity (default, success, error, warning, information, help) drives the entire dialog surface — header, body, and footer share the severity background and text. The six CSS custom-property pairs are aliased from the shared @teqbench/tbx-mat-severity-theme tokens, so the colored tiers stay independent of the active M3 theme palette while the default tier remains theme-responsive. Applications can opt into an inverted palette across every severity-aware @teqbench package by calling provideTbxMatSeverityTheme({ invert: true, applyToRoot: true }) at bootstrap.

The footer is a single flex row of buttons and form controls (checkboxes, toggles, radio groups, toggle groups). On dismiss, all collected control values are returned alongside the dismiss reason. Input dialogs project a consumer-defined component into the body — the component implements TbxMatDialogData<T> with two signals (isValid, value); the shell reads them to drive the affirm button's disabled state and to extract the form value on confirm.

The library is designed for Angular 21+ applications, and exposes a pluggable icon resolver so consumers can use Material Symbols font icons or bundled SVG icons without changing component code.

When to use

Dialogs are one of three message surfaces in the TeqBench component family. Choose based on the weight of the message and how much interaction it needs:

  • @teqbench/tbx-mat-notifications — small, transient messages with at most one action control. Ideally one line of text, two lines acceptable. Use notifications to acknowledge something without interrupting the user's flow.
  • @teqbench/tbx-mat-banners — wide, persistent messages with multiple action controls. Ideally one line of message text, up to three lines still acceptable. Use a banner when the message needs the user's attention and may offer a few follow-up choices.
  • @teqbench/tbx-mat-dialogs (this package) — heavier, focused interactions for arbitrary content. Use a dialog when the message is long, the choices are many, or the interaction is complex.

Reach for a dialog when a notification or a banner would be stretched past its envelope: long copy, many controls, multi-step input, or anything that demands the user's focused attention. If a banner is approaching the three-line limit or its actions group is growing beyond a handful of controls, that is the signal to promote it to a dialog.

At a glance

  • Severity-leveled API — success, error, warning, information, help, and default mirror the surface used by tbx-mat-banners and tbx-mat-notifications.
  • Dialog-only UX patterns — confirm (Yes/No) and input (projected form content with OK/Cancel) layered on top of severity.
  • Async by default — Every method returns Promise<TbxMatDialogResult<T, F>>; use await, no subscription management.
  • Typed input dialogs — TbxMatDialogData<T> contract with isValid and value signals; the affirm button's disabled state is automatically driven by isValid.
  • Rich footer controls — Buttons (text / filled / icon-position) and form controls (checkbox, toggle, radio group, toggle group) collected and returned on dismiss.
  • Pluggable icons — Three icon services ship out of the box (severity font, severity SVG, close font); consumers can subclass any of them or supply their own resolver.
  • Theming via CSS custom properties — Six severity background/text token pairs aliased from @teqbench/tbx-mat-severity-theme, plus centralized opacity tokens for action button variants.
  • Inverted palette flip — provideTbxMatSeverityTheme({ invert: true }) swaps background and text values app-wide; banners, notifications, and dialogs invert simultaneously.
  • Modal semantics — Backdrop, focus trap, escape-to-close, and aria-modal come from MatDialog; this package adds the chrome and the typed result surface.

Concepts

Severity level
A classification (default, success, error, warning, information, help) that selects the icon and color scheme applied to a dialog.
Dialog patterns
confirm and input are dialog-specific UX wrappers around the severity model — confirm defaults to Help severity with Yes/No buttons; input defaults to Information severity with a projected content component and OK/Cancel buttons.
Footer item
An entry in the dialog footer with a key (used in the returned footerValues record) and an align ('start' flows left, 'end' flows right). The first 'end' item gets margin-left auto, separating start- and end-aligned items.
Footer button emphasis
Visual weight of a footer button — 'primary' (filled, severity-colored) or 'text' (no fill). Destructive prompts are expressed via the dialog severity ('warning' or 'error'), not via a per-button variant.
Dismiss reason
The cause of a dialog closing — Affirm, Deny, Cancel, or Close. Footer buttons declare a result to map their click; backdrop click and Escape both emit Close with empty footer values.
Provider config
The DI-provided configuration (TBX_MAT_DIALOG_PROVIDER_CONFIG) that supplies the severity icon resolver and an optional close icon resolver. Required.
Content component
A consumer-defined @Component that implements TbxMatDialogData<T>. Used in the body of input dialogs; the shell reads isValid to drive the affirm button's disabled state and value to extract data on confirm.

Services

TbxMatDialogCloseFontIconService

Resolve the dialog close button to a font-based icon

Remarks

Default font-based close button icon service. Extends TbxMatFontIconService from @teqbench/tbx-mat-icons and registers the 'close' Material Symbols ligature. Used as the package-provided fallback for TbxMatDialogProviderConfig.closeIconResolverService when the consumer does not supply a custom close icon resolver.

No provider is registered automatically — when omitted from TbxMatDialogProviderConfig, the dialog shell instantiates this class with no fontSet argument and relies on the inherited fallback chain.

No default SVG close icon service is provided. Consumers who want SVG close icons must create a concrete subclass of TbxMatSvgIconService from @teqbench/tbx-mat-icons and provide it via TbxMatDialogProviderConfig.closeIconResolverService.

fontSet resolution

The fontSet is resolved by TbxMatFontIconService's fallback chain:

  1. Explicit constructor argument — new TbxMatDialogCloseFontIconService('material-symbols-sharp'). 2. TBX_MAT_FONT_ICON_DEFAULT_FONT_SET token — set once in app.config.ts. 3. MAT_ICON_DEFAULT_OPTIONS.fontSetAngular Material's global icon default. 4. Error — if none of the above provides a fontSet.

When to use

Provide as closeIconResolverService on TbxMatDialogProviderConfig when an explicit fontSet is required. Subclass to override the close ligature.

Example

// app.config.ts — explicit close icon font.
import {
    TBX_MAT_DIALOG_PROVIDER_CONFIG,
    TbxMatDialogSeverityFontIconService,
    TbxMatDialogCloseFontIconService,
} from '@teqbench/tbx-mat-dialogs';

providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService('material-symbols-rounded'),
            closeIconResolverService: new TbxMatDialogCloseFontIconService('material-symbols-rounded'),
        }),
    },
]

TbxMatDialogService

Open a typed modal dialog and await the user's choice

Remarks

Application-wide dialog service built on Angular Material's MatDialog. Provides nine opinionated dialog methods with sensible defaults and a general-purpose show() method for full control. All dialogs use the shared internal shell component for consistent chrome (header, body, footer).

Severity-leveled methods (success, error, warning, information, help, default) mirror the surface exposed by TbxMatBannerService and TbxMatNotificationService. Dialog-specific patterns (confirm, input) layer on top of the severity model with their own default footer presets.

All methods return a Promise that resolves when the dialog closes, so consumers use async/await with no subscription management.

Icons are resolved at render time by the dialog shell via the required TBX_MAT_DIALOG_PROVIDER_CONFIG injection token. Consumers configure the severity icon resolver (font or SVG) and an optional close icon resolver in app.config.ts; see TbxMatDialogProviderConfig for the full shape. Per-call TbxMatDialogConfig.icon overrides take precedence over the resolved severity icon and are rendered as font ligatures.

Error handling

When the dialog is dismissed via backdrop click or Escape without a button click, the underlying afterClosed() emits undefined. The service catches this case and returns a TbxMatDialogDismissReason.Close result with an empty footerValues record — dismissal is a negative action like Cancel or Deny and never carries form state.

When to use

Inject in any component or service that needs to prompt the user. Prefer the opinionated methods over show() so severity, icon, and footer defaults stay consistent across the application.

Example

private readonly dialog = inject(TbxMatDialogService);

// Severity methods (mirror banners/notifications).
await this.dialog.success({ title: 'Saved', message: 'Your changes are saved.' });
await this.dialog.error({ title: 'Failed', message: 'Could not save changes.' });
await this.dialog.warning({ title: 'Caution', message: 'This may take a while.' });
await this.dialog.information({ title: 'FYI', message: 'Heads up.' });
await this.dialog.help({ title: 'How it works', message: 'Tap to learn more.' });
await this.dialog.default({ title: 'Notice', message: 'Neutral surface.' });

// Confirmation — Help severity, Yes/No buttons.
const output = await this.dialog.confirm({ title: 'Continue?', message: 'Proceed?' });
if (output.result === TbxMatDialogDismissReason.Affirm) {
    // proceed
}

// Input — Information severity, OK/Cancel buttons.
// RenameFormComponent is a hypothetical consumer-defined component that
// implements TbxMatDialogData<string>.
const output = await this.dialog.input<string>({
    title: 'Rename',
    content: RenameFormComponent,
});

// Typed footer values.
interface MyFooter { dontAskAgain: boolean; }
const output = await this.dialog.confirm<MyFooter>({
    title: 'Delete',
    message: 'Are you sure?',
    footer: [
        { key: 'dontAskAgain', type: 'checkbox', label: "Don't ask again", align: 'start' },
        ...TBX_MAT_DIALOG_BUTTONS_YES_NO,
    ],
});

// Full control — no defaults applied.
const output = await this.dialog.show({
    title: 'Custom',
    icon: 'build',
    type: TbxMatSeverityLevel.Warning,
    message: 'Full control over every option.',
    footer: [...customFooter],
});

TbxMatDialogSeverityFontIconService

Resolve severity levels to font-based dialog icons

Remarks

Default font-based severity dialog icon service. Extends TbxMatSeverityFontIconService from @teqbench/tbx-mat-severity-theme and registers the shared default Material Symbols ligatures (TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES) for every severity level. The inherited resolve() and severity methods (default(), success(), error(), etc.) work via the registered mappings.

No provider is registered automatically — instantiate explicitly via the TBX_MAT_DIALOG_PROVIDER_CONFIG factory.

fontSet resolution

The fontSet is resolved by TbxMatFontIconService's fallback chain:

  1. Explicit constructor argument — new TbxMatDialogSeverityFontIconService('material-symbols-sharp'). 2. TBX_MAT_FONT_ICON_DEFAULT_FONT_SET token — set once in app.config.ts. 3. MAT_ICON_DEFAULT_OPTIONS.fontSetAngular Material's global icon default. 4. Error — if none of the above provides a fontSet.

When to use

Provide as severityIconResolverService on TbxMatDialogProviderConfig. Subclass to override individual ligatures.

Example 1

// app.config.ts — using with MAT_ICON_DEFAULT_OPTIONS.
import { MAT_ICON_DEFAULT_OPTIONS } from '@angular/material/icon';
import { TBX_MAT_DIALOG_PROVIDER_CONFIG, TbxMatDialogSeverityFontIconService }
    from '@teqbench/tbx-mat-dialogs';

providers: [
    { provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: 'material-symbols-rounded' } },
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService(),
        }),
    },
]

Example 2

// Using with an explicit fontSet.
providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService('material-symbols-rounded'),
        }),
    },
]

TbxMatDialogSeveritySvgIconService

Resolve severity levels to SVG dialog icons

Remarks

Default SVG-based severity dialog icon service. Extends TbxMatSeveritySvgIconService from @teqbench/tbx-mat-severity-theme and registers the shared default SVG icons (TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS) for every severity level. The inherited resolve() and severity methods (default(), success(), error(), etc.) work via the registered mappings.

No provider is registered automatically — instantiate explicitly via the TBX_MAT_DIALOG_PROVIDER_CONFIG factory.

Default icons ship with @teqbench/tbx-mat-severity-theme. Subclasses can override any default by overriding initialize() and calling register() with the same key and different SVG markup.

When to use

Provide as severityIconResolverService on TbxMatDialogProviderConfig when SVG icons are preferred over font ligatures. Subclass to override individual icons.

Example 1

// app.config.ts — using the defaults directly.
import { TBX_MAT_DIALOG_PROVIDER_CONFIG, TbxMatDialogSeveritySvgIconService }
    from '@teqbench/tbx-mat-dialogs';

providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeveritySvgIconService(),
        }),
    },
]

Example 2

// Subclassing with custom SVG markup.
import { Injectable } from '@angular/core';
import { TbxMatDialogSeveritySvgIconService } from '@teqbench/tbx-mat-dialogs';
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';

// MyDialogSvgIcons is a hypothetical consumer-defined subclass.
@Injectable()
export class MyDialogSvgIcons extends TbxMatDialogSeveritySvgIconService {
    protected override initialize(): void {
        super.initialize();
        this.register(TbxMatSeverityLevel.Success, '<svg>...</svg>');
    }
}

Interfaces

TbxMatDialogConfig

Configuration for opening a dialog via TbxMatDialogService

Remarks

The full configuration shape used by TbxMatDialogService.show(). The opinionated methods (success(), error(), etc.) accept TbxMatDialogConfigArgs instead, which makes every field except title optional.

Sizing fields (width, minWidth, maxWidth, minHeight, maxHeight) pass through to Angular Material's MatDialogConfig.

Type parameters

T

Type of data for input dialogs (the value produced by the projected content component implementing TbxMatDialogData). Defaults to void.

When to use

Used when calling TbxMatDialogService.show() for full control over every option. Most callers should use the opinionated methods, which apply sensible defaults.

Example

import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';

const config: TbxMatDialogConfig = {
    title: 'Custom Dialog',
    icon: 'build',
    type: TbxMatSeverityLevel.Warning,
    subtitle: 'Optional secondary line',
    contextBadge: 'Beta',
    message: 'Full control over every option.',
    footer: [
        { key: 'cancel', type: 'button', label: 'Cancel', result: TbxMatDialogDismissReason.Cancel, align: 'end' },
        { key: 'proceed', type: 'button', label: 'Proceed', emphasis: 'primary', result: TbxMatDialogDismissReason.Affirm, align: 'end' },
    ],
};

TbxMatDialogData

Contract for components rendered in dialog bodies

Remarks

The dialog shell reads isValid to drive the affirm button's disabled state and reads value to include in TbxMatDialogResult.data when the user confirms. Content components own their own form layout, validation, and state — the dialog system never inspects the content beyond these two signals.

Focus management

For input dialogs, the dialog service sets autoFocus: 'first-tabbable' so the consumer's cdkFocusInitial attribute on a form field inside the projected content component takes precedence. Content components should apply cdkFocusInitial to the element that should receive initial focus. This is a plain HTML attribute recognized by the Angular CDK FocusTrap — no directive import needed. Without it, focus would fall through to the first tabbable element in DOM order (typically the header close button), so applying it on the intended target is required for correct UX.

Non-input components (display-only content)

Components that display content without producing a form value use the null object pattern — isValid is always true (nothing to validate), value is always undefined (nothing to extract). This allows any component to be hosted via TbxMatDialogService.show() without type casts.

Type parameters

T

Type of value produced by the form content.

When to use

Implement on consumer-defined components passed to TbxMatDialogService.input() or TbxMatDialogService.show() via TbxMatDialogConfig.content.

Example

// Input dialog form content.
@Component({
    imports: [MatFormFieldModule, MatInputModule],
    template: `
        <mat-form-field>
            <input matInput cdkFocusInitial [ngModel]="name()" (ngModelChange)="name.set($event)" />
        </mat-form-field>
    `,
})
export class RenameFormComponent implements TbxMatDialogData<string> {
    readonly name = signal('');
    readonly isValid = computed(() => this.name().trim().length > 0);
    readonly value = this.name;
}

// Display-only content — null object pattern.
@Component({ ... })
export class UserSettingsComponent implements TbxMatDialogData<void> {
    readonly isValid = signal(true);
    readonly value = signal<void>(undefined);
}

TbxMatDialogFooterButton

Button footer item

Remarks

Clicking a button with a result closes the dialog and returns that result in TbxMatDialogResult. Buttons without a result perform side effects (e.g., navigation) without dismissing the dialog.

When to use

Add to a TbxMatDialogConfig.footer array, or use a button preset constant (TBX_MAT_DIALOG_BUTTONS_OK, etc.).

Example

const proceed: TbxMatDialogFooterButton = {
    key: 'proceed',
    type: 'button',
    label: 'Proceed',
    emphasis: 'primary',
    result: TbxMatDialogDismissReason.Affirm,
    align: 'end',
};

TbxMatDialogFooterCheckbox

Checkbox footer control

Remarks

Value is tracked in TbxMatDialogResult.footerValues as a boolean under the item's key.

When to use

Add to a TbxMatDialogConfig.footer array to collect a boolean alongside the dismiss action.

Example

const remember: TbxMatDialogFooterCheckbox = {
    key: 'remember',
    type: 'checkbox',
    label: "Don't ask again",
    align: 'start',
};

TbxMatDialogFooterItem

Base interface for all dialog footer items — buttons and form controls alike

Remarks

Every footer item has a key (used in the returned TbxMatDialogResult.footerValues record) and an align (determines left or right positioning in the footer row).

The footer is a single flex row. Items render in caller-specified array order. The first align: 'end' item receives margin-left: auto, pushing it and all subsequent items to the right side.

When to use

Not used directly — extend via the discriminated members of TbxMatDialogFooterControlType.

Example

// Implementations are the concrete footer item interfaces.
const item: TbxMatDialogFooterButton = {
    key: 'ok',
    type: 'button',
    label: 'OK',
    emphasis: 'primary',
    result: TbxMatDialogDismissReason.Affirm,
    align: 'end',
};

TbxMatDialogFooterRadioGroup

Radio group footer control — single-select from a set of options

Remarks

Value is tracked in TbxMatDialogResult.footerValues as a string under the item's key.

When to use

Add to a TbxMatDialogConfig.footer array to let the user pick one option from a small set (typically two to four).

Example

const visibility: TbxMatDialogFooterRadioGroup = {
    key: 'visibility',
    type: 'radio-group',
    options: [
        { label: 'Public', value: 'public' },
        { label: 'Private', value: 'private' },
    ],
    initialValue: 'public',
    align: 'start',
};

TbxMatDialogFooterToggle

Slide toggle footer control

Remarks

Value is tracked in TbxMatDialogResult.footerValues as a boolean under the item's key.

When to use

Add to a TbxMatDialogConfig.footer array to collect a boolean alongside the dismiss action — visually distinct from a checkbox.

Example

const notify: TbxMatDialogFooterToggle = {
    key: 'notify',
    type: 'toggle',
    label: 'Email notifications',
    initialValue: true,
    align: 'start',
};

TbxMatDialogFooterToggleGroup

Button toggle group footer control — single-select or multi-select

Remarks

Value is tracked in TbxMatDialogResult.footerValues as a string (single-select) or string[] (multi-select) under the item's key.

When to use

Add to a TbxMatDialogConfig.footer array to let the user pick from a set of options rendered as a toggle button group. Use multiple: true to allow several selections.

Example

const align: TbxMatDialogFooterToggleGroup = {
    key: 'align',
    type: 'toggle-group',
    options: [
        { label: 'Left', value: 'left', icon: 'format_align_left' },
        { label: 'Center', value: 'center', icon: 'format_align_center' },
        { label: 'Right', value: 'right', icon: 'format_align_right' },
    ],
    initialValue: 'left',
    align: 'start',
};

TbxMatDialogProviderConfig

Configuration for the dialog component's injectable dependencies

Remarks

Provided via the TBX_MAT_DIALOG_PROVIDER_CONFIG injection token in app.config.ts. Groups all dialog icon customization into a single provider entry, matching the pattern used by TbxMatBannerProviderConfig and TbxMatNotificationProviderConfig.

No provider is registered automatically — consumers must explicitly provide TBX_MAT_DIALOG_PROVIDER_CONFIG for the dialog component to render.

Properties

When to use

Provide in app.config.ts to wire icon resolution. Required.

Example 1

// app.config.ts — font icons with explicit fontSet.
import { TBX_MAT_DIALOG_PROVIDER_CONFIG, TbxMatDialogSeverityFontIconService }
    from '@teqbench/tbx-mat-dialogs';

providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService('material-symbols-rounded'),
        }),
    },
]

Example 2

// SVG icons.
providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeveritySvgIconService(),
        }),
    },
]

Example 3

// With a custom close icon resolver.
// MyCloseIconService is a hypothetical consumer-defined service that extends
// TbxMatFontIconService<string> or TbxMatSvgIconService<string> and registers
// an icon under the 'close' key.
providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService('material-symbols-rounded'),
            closeIconResolverService: new MyCloseIconService('material-symbols-rounded'),
        }),
    },
]

TbxMatDialogResult

Typed output returned when a dialog closes

Remarks

Resolved by every TbxMatDialogService method. Carries the user's action (TbxMatDialogDismissReason), any data produced by an input dialog's projected content component, and any values collected from footer form controls.

On any non-Affirm dismissal (Deny, Cancel, Close, Escape, backdrop), data is undefined and footerValues is an empty object — negative actions never carry state that implies confirmation.

Type parameters

T

Type of data returned by input dialogs (from TbxMatDialogData.value). Defaults to void for informational and confirmation dialogs.

F

Type of footer control values. Defaults to Record<string, unknown>. Callers that need typed footer values specify an interface as the second generic parameter.

When to use

The return shape of every TbxMatDialogService method. await a dialog call and branch on result to handle the user's action.

Example

// Simple confirmation — both generics use defaults.
const output: TbxMatDialogResult = await dialog.confirm({ title: 'Continue?' });

// Input dialog with typed data.
const output: TbxMatDialogResult<string> = await dialog.input<string>({
    title: 'Rename',
    content: RenameFormComponent, // hypothetical consumer-defined component
});

// Confirmation with typed footer values.
interface MyFooter { dontAskAgain: boolean; }
const output: TbxMatDialogResult<void, MyFooter> = await dialog.confirm<MyFooter>({
    title: 'Delete?',
});

Enums

TbxMatDialogDismissReason

Identify which action closed a dialog

Remarks

Returned as TbxMatDialogResult.result when the dialog closes.

  • Affirm — User confirmed the action (OK, Yes, Save, Delete, etc.). - Deny — User explicitly declined (No). - Cancel — User aborted the interaction (Cancel button). - Close — User dismissed without choosing (close button, Escape, backdrop).

When to use

Compare TbxMatDialogResult.result against the enum members to branch on the user's action. Footer button declarations carry a result field that maps the click to one of these values.

Example

const output = await dialog.confirm({ title: 'Delete?', message: 'This cannot be undone.' });
if (output.result === TbxMatDialogDismissReason.Affirm) {
    // proceed with deletion
}

Types

TbxMatDialogConfigArgs

Convenience type for the opinionated dialog methods (success, error, warning, information, help, default, confirm, input)

Remarks

Requires a title — all other TbxMatDialogConfig fields are optional. Callers specify only what they want to override; the service merges in defaults for severity type and footer button preset.

Type parameters

T

Type of data for input dialogs. Defaults to void.

When to use

Used as the parameter type for the opinionated TbxMatDialogService methods. Use TbxMatDialogConfig directly when calling show(), which applies no defaults.

Example

await dialog.success({ title: 'Saved' });
await dialog.warning({ title: 'Caution', message: 'This may take a while.' });

TbxMatDialogFooterControlType

Discriminated union of all dialog footer item types

Remarks

The dialog shell component renders each item via @switch (control.type), and TypeScript narrows the type automatically in each branch. Members are TbxMatDialogFooterButton, TbxMatDialogFooterCheckbox, TbxMatDialogFooterToggle, TbxMatDialogFooterRadioGroup, and TbxMatDialogFooterToggleGroup.

When to use

Use as the element type when assembling a custom footer array on a TbxMatDialogConfig or a TbxMatDialogConfigArgs.

Example

const footer: readonly TbxMatDialogFooterControlType[] = [
    { key: 'remember', type: 'checkbox', label: 'Remember me', align: 'start' },
    { key: 'cancel', type: 'button', label: 'Cancel', result: TbxMatDialogDismissReason.Cancel, align: 'end' },
    { key: 'ok', type: 'button', label: 'OK', emphasis: 'primary', result: TbxMatDialogDismissReason.Affirm, align: 'end' },
];

TbxMatDialogIconResolver

Icon resolver that also exposes the resolved icon's type

Remarks

Combines TbxMatIconResolver from @teqbench/tbx-mat-icons with the static iconType property the dialog template needs to decide whether to render a font ligature or an SVG element.

When to use

The shape of the optional closeIconResolverService slot on TbxMatDialogProviderConfig. Custom close icon services must conform to this shape — extending TbxMatFontIconService<string> or TbxMatSvgIconService<string> from @teqbench/tbx-mat-icons provides it automatically.

Example

// MyCloseIconService is a hypothetical consumer-defined service.
const resolver: TbxMatDialogIconResolver = new MyCloseIconService();
const icon = resolver.resolve('close');
const type = resolver.iconType; // 'font' | 'svg'

Constants

TBX_MAT_DIALOG_BUTTONS_OK_CANCEL

OK + Cancel buttons preset — Cancel left, OK right

Remarks

Default footer for the input method.

When to use

Use when the dialog requires a positive commit and offers an explicit cancel path.

Example

await dialog.show({
    title: 'Rename',
    content: RenameFormComponent, // hypothetical consumer-defined component
    footer: TBX_MAT_DIALOG_BUTTONS_OK_CANCEL,
});

TBX_MAT_DIALOG_BUTTONS_OK

Single OK button preset — right-aligned, primary emphasis

Remarks

Default footer for the severity-leveled methods (success, error, warning, information, help, default).

When to use

Spread into a custom footer array, or pass directly as the footer field. Use when the dialog only needs an acknowledgement.

Example

await dialog.show({ title: 'Saved', message: 'Done.', footer: TBX_MAT_DIALOG_BUTTONS_OK });

TBX_MAT_DIALOG_BUTTONS_YES_NO_CANCEL

Yes + No + Cancel buttons preset — Cancel left, No and Yes right

When to use

Use when the dialog asks a binary question and also needs a third option to back out without committing to either answer.

Example

await dialog.show({
    title: 'Save changes?',
    message: 'You have unsaved changes.',
    footer: TBX_MAT_DIALOG_BUTTONS_YES_NO_CANCEL,
});

TBX_MAT_DIALOG_BUTTONS_YES_NO

Yes + No buttons preset — both right-aligned, Yes primary

Remarks

Default footer for the confirm method.

When to use

Use when the dialog asks a binary question without a "back out" path.

Example

await dialog.show({
    title: 'Continue?',
    message: 'Are you sure?',
    footer: TBX_MAT_DIALOG_BUTTONS_YES_NO,
});

TBX_MAT_DIALOG_PROVIDER_CONFIG

Injection token for dialog component icon configuration

Remarks

Required. Provide in app.config.ts to configure the severity icon resolver service and the close button icon. Use TbxMatDialogSeverityFontIconService for font icons or TbxMatDialogSeveritySvgIconService for SVG icons — both ship with sensible defaults from @teqbench/tbx-mat-severity-theme.

No provider is registered automatically — without an explicit provider, the dialog component will not render.

When to use

Provide in app.config.ts with a TbxMatDialogProviderConfig factory.

Example 1

// app.config.ts — font icons with explicit fontSet.
import { TBX_MAT_DIALOG_PROVIDER_CONFIG, TbxMatDialogSeverityFontIconService }
    from '@teqbench/tbx-mat-dialogs';

providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService('material-symbols-rounded'),
        }),
    },
]

Example 2

// Font icons via MAT_ICON_DEFAULT_OPTIONS (no explicit fontSet).
import { MAT_ICON_DEFAULT_OPTIONS } from '@angular/material/icon';
import { TBX_MAT_DIALOG_PROVIDER_CONFIG, TbxMatDialogSeverityFontIconService }
    from '@teqbench/tbx-mat-dialogs';

providers: [
    { provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: 'material-symbols-rounded' } },
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService(),
        }),
    },
]

Example 3

// With a custom close icon resolver.
// MyCloseIconService is a hypothetical consumer-defined service that extends
// TbxMatFontIconService<string> or TbxMatSvgIconService<string> and registers
// an icon under the 'close' key.
providers: [
    {
        provide: TBX_MAT_DIALOG_PROVIDER_CONFIG,
        useFactory: () => ({
            severityIconResolverService: new TbxMatDialogSeverityFontIconService('material-symbols-rounded'),
            closeIconResolverService: new MyCloseIconService('material-symbols-rounded'),
        }),
    },
]

Accessibility

  • Modal semantics. Dialogs render via Angular Material's MatDialog, which sets aria-modal="true", manages the backdrop, and traps keyboard focus inside the overlay until dismissal. The title is the dialog's aria-labelledby target via matDialogTitle.
  • Focus. Initial focus depends on what the dialog contains. When the dialog has an affirm button (any footer button with result: TbxMatDialogDismissReason.Affirm), the shell auto-applies cdkFocusInitial to that button so it receives initial focus. When the dialog projects a content component, focus follows the consumer's cdkFocusInitial attribute on a form field — applying it is the consumer's responsibility, and is recognized by the CDK FocusTrap without any directive import. When neither is present (footerless show() calls or footers with only passive dismiss buttons), autoFocus falls back to 'dialog' so initial focus lands on the dialog container, not the close button. The close button is reachable via Tab in every case.
  • Keyboard. Escape dismisses the dialog with Close unless disableClose: true is set. Tab cycles through focusable elements within the dialog. Footer buttons activate on Enter and Space; form controls use their native Angular Material keyboard behavior.
  • Reduced motion. Angular Material's MatDialog honors prefers-reduced-motion: reduce for its open/close animation.
  • Color contrast. The default severity palette meets WCAG AA contrast for text on each severity background. Overriding the severity CSS custom properties is the consumer's responsibility to re-verify.
  • Icons. Severity and close icons are decorative and marked aria-hidden; meaning is carried by the title and message text and by the close button's aria-label.