@teqbench/tbx-mat-banners provides persistent, attention-grabbing messages for Angular applications. It fills the gap between small transient notifications and heavier modal dialogs: a wide, horizontally full banner that can carry a short message, a severity indicator, and a small group of action controls, and that stays on screen until the user — or application code — dismisses it.
Two display modes are supported from a single component surface. In overlay mode, TbxMatBannerService creates banners via CDK Overlay on a FIFO queue, one at a time, with optional slide or fade animation and programmatic dismiss. In inline mode, TbxMatBannerComponent is placed directly in a template, controlled by the consumer via bindings, and emits dismiss events.
Severity (default, success, error, warning, information, help) drives both the icon and the color scheme. The six CSS custom-property pairs are aliased from the shared `@teqbench/tbx-mat-severity-theme` tokens, so the five colored tiers stay independent of the active M3 theme palette while the default tier remains theme-responsive. Applications can opt into an inverted palette (white backgrounds with colored text) across every severity-aware @teqbench package by calling provideTbxMatSeverityTheme({ invert: true, applyToRoot: true }) at bootstrap — the flag is app-global and affects notifications and dialogs simultaneously, not banners alone. An optional actions group accepts any mix of buttons, checkboxes, toggles, radio groups, and toggle groups; on dismiss, all collected values are returned alongside the dismiss reason and the action key that triggered it.
The library is designed for Angular 21+ zoneless applications, uses signal inputs, honors prefers-reduced-motion, 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
Banners 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 (this package) — 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` — heavier, focused interactions for arbitrary content. Use a dialog when the message is long, the choices are many, or the interaction is complex.
If the content you are putting in a banner is approaching the three-line limit, or if the actions group is growing beyond a handful of controls, that is a signal to escalate to a dialog instead. A banner that behaves like a miniature dialog loses the affordances of both.
At a glance
- Two display modes — Overlay service for fire-and-forget messages and inline component for template-driven use.
- Severity-leveled API — Convenience methods for default, success, error, warning, information, and help with matching icons and colors.
- Actions group — Buttons and form controls (checkbox, toggle, radio group, toggle group) in a single message.
- FIFO queue — One banner at a time, with signal-based isActive and pendingCount state.
- Dismiss tracking — Promise resolves with dismiss reason, action key, and collected form control values.
- Indefinite by default — Banners persist until dismissed; positive duration auto-dismisses, negative is treated as indefinite.
- Animations — Optional slide or fade on overlay banners; automatically disabled under prefers-reduced-motion.
- Theming via CSS custom properties — Per-severity colors, gaps, padding, shadow, and z-index exposed as CSS variables.
- Pluggable icons — Font (Material Symbols) or SVG icon resolver service via DI token.
- Responsive layout — CSS container queries reflow the actions group onto a second row on narrow viewports.
- Zoneless ready — Built for Angular 21+ zoneless applications using signal inputs.
Concepts
- Severity level — A classification (default, success, error, warning, information, help) that selects the icon and color scheme applied to a banner.
- Actions group — An ordered list of action controls — buttons and form controls — rendered inside the banner and whose values are returned on dismiss.
- Dismiss reason — The cause of a banner closing — user action, close button, timeout, or one of two programmatic paths (single or all).
- Queue — A FIFO list of pending banners. One banner is visible at a time in overlay mode; queued banners render in order as each resolves.
- Provider config — The DI-provided configuration (TBX_MAT_BANNER_PROVIDER_CONFIG) that supplies the severity icon resolver, optional close icon resolver, and default animation.
- Inline mode — Using TbxMatBannerComponent directly in a consumer template, with visibility and state controlled by the consumer rather than the service.
- Overlay mode — Using TbxMatBannerService to render a banner in a CDK Overlay above the application, positioned at the top or bottom of the viewport.
Services
TbxMatBannerCloseFontIconService
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 default for TbxMatBannerProviderConfig.closeIconResolverService when the consumer does not supply a custom close icon resolver.
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 TbxMatBannerProviderConfig.closeIconResolverService.
fontSet resolution
The fontSet is resolved by TbxMatFontIconService's fallback chain:
- Explicit constructor argument —
new TbxMatBannerCloseFontIconService('material-symbols-sharp')
TBX_MAT_FONT_ICON_DEFAULT_FONT_SET token — set once in app.config.ts
MAT_ICON_DEFAULT_OPTIONS.fontSet — Angular Material's global icon default
- Error — if none of the above provides a fontSet
Example
Using with MAT_ICON_DEFAULT_OPTIONS:
import { MAT_ICON_DEFAULT_OPTIONS } from '@angular/material/icon';
import { TBX_MAT_BANNER_PROVIDER_CONFIG, TbxMatBannerSeverityFontIconService }
from '@teqbench/tbx-mat-banners';
providers: [
{ provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: 'material-symbols-rounded' } },
{
provide: TBX_MAT_BANNER_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBannerSeverityFontIconService(),
}),
},
]
TbxMatBannerService
Application-wide banner service for overlay display
Creates full-width banners via Angular CDK Overlay with typed severity levels, configurable duration, and an actions group supporting buttons and form controls.
Banners are queued FIFO and displayed one at a time. When the current banner is dismissed (manually or by timeout), the next queued banner is shown automatically.
All public methods return a TbxMatBannerRef synchronously, containing the consumer's config and a result promise that resolves with a TbxMatBannerResult when the banner is dismissed.
Consumers who do not need the ref or result should use the void prefix to suppress unhandled-promise lint warnings:
void this.bannerService.success('Saved');
Queue state is exposed via Angular signals: - isActive() — whether a banner is currently visible - pendingCount() — number of banners waiting in the queue
When to use
Inject the service and call the convenience methods for each severity level (success(), error(), warning(), information(), help(), default()). Use show() when full control over configuration is needed. Use dismiss() and dismissAll() to programmatically clear banners.
Example
Fire-and-forget:
private readonly banner = inject(TbxMatBannerService);
void this.banner.success('Item saved successfully.');
void this.banner.error('Failed to load data. Please try again.');
Example
Reacting to action dismissal with form values:
const ref = this.banner.warning('Update available', {
actionsGroup: [
{ type: 'checkbox', key: 'autoUpdate', label: 'Auto-update' },
{ type: 'button', key: 'update', label: 'Update', appearance: 'filled' },
{ type: 'button', key: 'later', label: 'Later' },
],
});
const result = await ref.result;
if (result.actionKey === 'update') {
const autoUpdate = result.actionsGroupValues['autoUpdate'] as boolean;
this.performUpdate(autoUpdate);
}
TbxMatBannerSeverityFontIconService
Default font-based severity banner 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.
fontSet resolution
The fontSet is resolved by TbxMatFontIconService's fallback chain:
- Explicit constructor argument —
new TbxMatBannerSeverityFontIconService('material-symbols-sharp')
TBX_MAT_FONT_ICON_DEFAULT_FONT_SET token — set once in app.config.ts
MAT_ICON_DEFAULT_OPTIONS.fontSet — Angular Material's global icon default
- Error — if none of the above provides a fontSet
Example
Using with MAT_ICON_DEFAULT_OPTIONS:
import { MAT_ICON_DEFAULT_OPTIONS } from '@angular/material/icon';
import { TBX_MAT_BANNER_PROVIDER_CONFIG, TbxMatBannerSeverityFontIconService }
from '@teqbench/tbx-mat-banners';
providers: [
{ provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: 'material-symbols-rounded' } },
{
provide: TBX_MAT_BANNER_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBannerSeverityFontIconService(),
}),
},
]
Example
Using with an explicit fontSet:
import { TBX_MAT_BANNER_PROVIDER_CONFIG, TbxMatBannerSeverityFontIconService }
from '@teqbench/tbx-mat-banners';
providers: [
{
provide: TBX_MAT_BANNER_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBannerSeverityFontIconService('material-symbols-rounded'),
}),
},
]
TbxMatBannerSeveritySvgIconService
Default SVG-based severity banner 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.
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.
Example
Using the defaults directly:
import { TBX_MAT_BANNER_PROVIDER_CONFIG, TbxMatBannerSeveritySvgIconService }
from '@teqbench/tbx-mat-banners';
providers: [
{
provide: TBX_MAT_BANNER_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBannerSeveritySvgIconService(),
}),
},
]
Example
Subclassing with custom SVG markup:
import { Injectable } from '@angular/core';
import { TbxMatBannerSeveritySvgIconService } from '@teqbench/tbx-mat-banners';
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';
@Injectable()
export class MyBannerSvgIcons extends TbxMatBannerSeveritySvgIconService {
protected override initialize(): void {
super.initialize();
this.register(TbxMatSeverityLevel.Success, '<svg>...</svg>');
}
}
Components
TbxMatBannerComponent
Banner content component for both inline and overlay display
Renders a severity-styled banner with an optional severity icon, message, actions group (buttons and form controls), and close button.
Display Modes
Overlay mode: Created by TbxMatBannerService via CDK Overlay. Receives data through the TBX_MAT_BANNER_DATA injection token. Consumers do not instantiate the component directly in this mode.
Inline mode: Placed directly in a consumer's template. Receives data through signal inputs and emits dismiss events via outputs.
Template element order
severity icon→message→actions group→close button
All elements are optional except the message. The actions group and close button render in the actions slot.
Actions group rendering
Controls render in array order via @switch (control.type). Form control values are tracked internally via writable signals initialized from each control's defaultValue. Current values are collected into the actionsGroupValues record on dismiss.
Example
Overlay mode (consumers do not instantiate directly):
void this.bannerService.success('Item saved.');
Example
Inline mode:
<tbx-mat-banner [type]="severityLevel" [message]="'Hello'" (dismissed)="onDismiss($event)" />
Interfaces
TbxMatBannerActionButton
Button control in a banner actions group
Defines a clickable button rendered in the banner's actions group slot (between the message and the close button). Clicking the button dismisses the banner. The button's key is included in TbxMatBannerResult.actionKey so the consumer can identify which button triggered the dismissal.
Each button specifies its own appearance and optional icon. The severity panel SCSS provides color token overrides for all six Angular Material button variants, so a 'filled' button inside a success banner automatically receives the success color treatment.
When to use
Add one or more buttons to the actionsGroup array on TbxMatBannerConfig to let users respond inline (e.g., undo, retry, dismiss with intent).
Example
Text button:
{ type: 'button', key: 'undo', label: 'Undo' }
Example
Filled button with icon:
{
type: 'button',
key: 'retry',
label: 'Retry',
icon: 'refresh',
appearance: 'filled',
actionIconResolverService: myIconService,
}
Example
Icon-only button:
{
type: 'button',
key: 'settings',
label: 'Settings',
icon: 'settings',
appearance: 'icon',
actionIconResolverService: myIconService,
}
TbxMatBannerActionCheckbox
Checkbox control in a banner actions group
Renders a MatCheckbox in the banner's actions group slot. The checkbox value is tracked internally by the banner component and included in TbxMatBannerResult.actionsGroupValues as a boolean under this control's key when the banner is dismissed.
When to use
Add a checkbox to the actionsGroup array on TbxMatBannerConfig to collect a boolean preference alongside the banner's message.
Example
{ type: 'checkbox', key: 'dontShowAgain', label: "Don't show again", defaultValue: false }
TbxMatBannerActionRadioGroup
Radio group control in a banner actions group
Renders a MatRadioGroup with MatRadioButton options in the banner's actions group slot. The selected value is tracked internally by the banner component and included in TbxMatBannerResult.actionsGroupValues as a string under this control's key when the banner is dismissed.
When to use
Add a radio group to the actionsGroup array on TbxMatBannerConfig to collect a single-select choice alongside the banner's message.
Example
{
type: 'radio-group',
key: 'priority',
options: [
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
],
defaultValue: 'medium',
}
TbxMatBannerActionToggle
Slide toggle control in a banner actions group
Renders a MatSlideToggle in the banner's actions group slot. The toggle value is tracked internally by the banner component and included in TbxMatBannerResult.actionsGroupValues as a boolean under this control's key when the banner is dismissed.
When to use
Add a toggle to the actionsGroup array on TbxMatBannerConfig to collect a boolean preference alongside the banner's message.
Example
{ type: 'toggle', key: 'autoRetry', label: 'Auto-retry', defaultValue: true }
TbxMatBannerActionToggleGroup
Button toggle group control in a banner actions group
Renders a MatButtonToggleGroup with MatButtonToggle options in the banner's actions group slot. The selected value is tracked internally by the banner component and included in TbxMatBannerResult.actionsGroupValues as a string (single-select) or string[] (multi-select) under this control's key when the banner is dismissed.
When to use
Add a toggle group to the actionsGroup array on TbxMatBannerConfig to collect a selection alongside the banner's message.
Example
Single-select:
{
type: 'toggle-group',
key: 'format',
options: [
{ label: 'JSON', value: 'json' },
{ label: 'CSV', value: 'csv' },
],
defaultValue: 'json',
}
Example
Multi-select with icons:
{
type: 'toggle-group',
key: 'channels',
multiple: true,
options: [
{ label: 'Email', value: 'email', icon: 'email' },
{ label: 'SMS', value: 'sms', icon: 'sms' },
],
defaultValue: ['email'],
}
TbxMatBannerRef
Reference to a queued or active banner
Returned synchronously from all TbxMatBannerService methods (show(), success(), error(), warning(), information(), help()). Contains two members:
config — the consumer-provided configuration, available immediately. - result — a promise that resolves with a TbxMatBannerResult containing the TbxMatBannerDismissReason, the actionKey of the button that triggered dismissal (if applicable), and the actionsGroupValues record when the banner is dismissed.
Fire-and-Forget Usage
Consumers who do not need the dismiss result should prefix the call with void to suppress unhandled-promise lint warnings:
void this.bannerService.success('Saved');
When to use
Capture the returned ref to react to banner dismissal or inspect the original config.
Example
Reacting to action dismissal with form values:
const ref = this.bannerService.warning('Update available', {
actionsGroup: [
{ type: 'checkbox', key: 'autoUpdate', label: 'Auto-update' },
{ type: 'button', key: 'update', label: 'Update', appearance: 'filled' },
],
});
const result = await ref.result;
if (result.actionKey === 'update') {
const autoUpdate = result.actionsGroupValues['autoUpdate'] as boolean;
this.performUpdate(autoUpdate);
}
Example
Fire-and-forget:
void this.bannerService.success('Saved');
TbxMatBannerResult
Result returned when a banner is dismissed
Resolved by the TbxMatBannerRef.result promise when a banner is dismissed for any reason — user action, timeout, or programmatic dismissal. The dismissReason property indicates which trigger caused the dismissal. When an action button triggered the dismissal, actionKey identifies the button. Form control values from the actions group are collected in actionsGroupValues.
When to use
Await the result promise from any TbxMatBannerService method to determine how a banner was dismissed and retrieve collected values.
Example
const ref = this.bannerService.warning('Update available', {
actionsGroup: [
{ type: 'checkbox', key: 'autoUpdate', label: 'Auto-update', defaultValue: false },
{ type: 'button', key: 'update', label: 'Update Now', appearance: 'filled' },
{ type: 'button', key: 'later', label: 'Later' },
],
});
const result: TbxMatBannerResult = await ref.result;
if (result.actionKey === 'update') {
const autoUpdate = result.actionsGroupValues['autoUpdate'] as boolean;
this.performUpdate(autoUpdate);
}
Enums
TbxMatBannerAnimation
Enter/exit animation mode for overlay banners
Controls the motion applied to an overlay banner as it appears and disappears. Values map to CSS classes defined in src/styles/_tbx-mat-banners.scss that drive keyframe animations on the CDK Overlay panel:
None — no animation. The banner appears and disappears instantly. - Slide — slides in from the closest viewport edge based on TbxMatBannerConfig.verticalPosition, and slides out the same way on dismiss. - Fade — fades in and out via opacity.
Consumers can tune motion timing via four CSS custom properties: --tbx-mat-banner-anim-enter-duration, --tbx-mat-banner-anim-enter-easing, --tbx-mat-banner-anim-exit-duration, and --tbx-mat-banner-anim-exit-easing. Animations are automatically disabled when the user has prefers-reduced-motion: reduce set at the OS level.
When to use
Set per banner via TbxMatBannerConfig.animation, or set an application-wide default via TbxMatBannerProviderConfig.defaultAnimation. A per-banner value always wins over the provider default.
Example
this.banner.success('Saved.', { animation: TbxMatBannerAnimation.Slide });
TbxMatBannerDismissReason
Reason a banner was dismissed
Returned as part of TbxMatBannerResult via TbxMatBannerRef.result. Each value corresponds to a distinct dismissal trigger:
Action — the user clicked an action button in the actions group. - Close — the user clicked the close button. - Timeout — the banner auto-dismissed after the configured duration expired. - ProgrammaticDismissAll — TbxMatBannerService.dismissAll was called, clearing the queue and dismissing the active banner. - ProgrammaticDismissCurrent — TbxMatBannerService.dismiss was called, dismissing only the currently active banner.
When to use
Inspect the dismiss reason after awaiting the result promise to determine which user or programmatic action closed the banner.
Example
const ref = this.bannerService.success('Item deleted', {
actionsGroup: [{ type: 'button', key: 'undo', label: 'Undo' }],
duration: 30_000,
});
const result = await ref.result;
if (result.dismissReason === TbxMatBannerDismissReason.Action) {
this.undoDelete();
}
Types
TbxMatBannerActionButtonAppearance
Visual appearance of a banner action button
Union of MatButtonAppearance ('text' | 'filled' | 'elevated' | 'outlined' | 'tonal') and the custom 'icon' value for icon-only action buttons.
Values other than 'icon' map directly to the [appearance] input on Angular Material button directives. The 'icon' value renders a mat-icon-button instead.
This type is coupled to MatButtonAppearance from @angular/material/button. If Angular Material renames, removes, or adds values to that type, this type will need a corresponding update.
Each button in the actions group specifies its own appearance. When omitted, defaults to 'text'.
When to use
Specify the action button appearance when the default 'text' style is not desired.
Example
this.bannerService.warning('Connection lost', {
actionsGroup: [{
type: 'button',
key: 'retry',
label: 'Retry',
appearance: 'tonal',
}],
});
this.bannerService.error('Upload failed', {
actionsGroup: [{
type: 'button',
key: 'retry',
label: 'Retry',
icon: 'refresh',
appearance: 'icon',
}],
});
TbxMatBannerActionsGroupControl
Discriminated union of all banner actions group control types
Each control in a banner's actionsGroup array must be one of these types. The type property serves as the discriminant for type narrowing in \@switch blocks and conditional logic.
Controls are rendered in the slot between the banner's message and close button, in array order.
'button' — TbxMatBannerActionButton — clickable button that dismisses the banner - 'checkbox' — TbxMatBannerActionCheckbox — boolean checkbox control - 'toggle' — TbxMatBannerActionToggle — slide toggle control - 'radio-group' — TbxMatBannerActionRadioGroup — single-select radio group - 'toggle-group' — TbxMatBannerActionToggleGroup — button toggle group (single or multi-select)
When to use
Use this type when declaring the actionsGroup array on TbxMatBannerConfig to ensure type safety across all control types.
Example
const actionsGroup: TbxMatBannerActionsGroupControl[] = [
{ type: 'checkbox', key: 'dontShowAgain', label: "Don't show again" },
{ type: 'button', key: 'dismiss', label: 'Dismiss' },
{ type: 'button', key: 'retry', label: 'Retry', appearance: 'filled' },
];
Accessibility
- Overlay container. Overlay banners render inside a CDK Overlay pane positioned at the top or bottom of the viewport. The overlay is non-blocking and does not trap focus. Consumers that need screen-reader announcement of new banners should wrap the banner message in a container with
aria-live="polite" in their application shell, or use the existing LiveAnnouncer service to announce the message text alongside the banner call.
- Keyboard. The close button and every control in the actions group are focusable in DOM order.
Enter and Space activate buttons; form controls use their native Angular Material keyboard behavior.
- Focus. Focus is not moved into the banner automatically — banners are non-blocking. Consumers that need to direct attention to a banner action should call
focus() on the control explicitly, or escalate to a dialog.
- Reduced motion. When
prefers-reduced-motion: reduce is set, the Slide and Fade animations are bypassed and banners show/hide instantly regardless of the configured animation.
- Color contrast. The default severity palette meets WCAG AA contrast for body text on each background. Overriding the severity CSS custom properties is the consumer's responsibility to re-verify.
- Icons. Severity icons are decorative and marked
aria-hidden; the severity meaning is carried by the message text itself, not by the icon alone.