toast-message-display
v22.0.4
Published
This is an Angular Module containing Components/Services using Material
Downloads
316
Readme
Toast Message Display
Overview
toast-message-display provides a toast/snackbar notification system for Angular applications, built on Angular Material's MatSnackBar. It supports two render targets from a single call - a Material snackbar (one visible at a time) or an inline, in-page list (multiple visible concurrently) - backed by one shared, signal-based queue.
Features
- Two display targets, one API -
'snackbar'(default) or'inline', chosen per call - Six color themes - SUCCESS, ERROR, INFO, WARN, NOTIFY, GENERAL
- Flexible positioning - top or bottom
- Action buttons - optional, with custom text (or a close icon via
action: '-') - Icon support - Material icons alongside the message
- Duration control - auto-dismiss after N milliseconds, or
0for manual-dismiss-only - Signal-based state - the service exposes
snackbarQueueandinlineToastsas computed signals
Installation & Setup
1. Import the module
// app.module.ts
import { ToastMessageDisplayModule } from 'toast-message-display';
@NgModule({
imports: [
ToastMessageDisplayModule
]
})
export class AppModule { }2. Dependencies
npm install @angular/material @angular/cdkService API
ToastMessageDisplayService.toastMessage(options, duration?, vertical?, target?)
Queues a toast for display.
| Parameter | Type | Default | Description |
|------------|----------------------------------|----------------|--------------|
| options | ToastDisplay | required | Message, color, icon, and optional action |
| duration | number (milliseconds) | service default (3000ms) | Auto-dismiss timing. Pass 0 for manual dismiss only (matches Angular Material's own MatSnackBarConfig.duration convention). Honored exactly as passed, regardless of whether options.action is set. |
| vertical | VerticalAlignment | 'top' | 'top' or 'bottom' - only affects target: 'snackbar' |
| target | 'snackbar' \| 'inline' | 'snackbar' | Which display renders the toast |
import { Component, inject } from '@angular/core';
import { ToastMessageDisplayService, ToastDisplay, ToastColors } from 'toast-message-display';
@Component({
selector: 'app-success-example',
template: `<button (click)="showSuccess()">Show Success Message</button>`
})
export class SuccessExampleComponent {
private toastService = inject(ToastMessageDisplayService);
showSuccess() {
const display = ToastDisplay.adapt({
message: 'Data saved successfully!',
action: 'OK',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});
this.toastService.toastMessage(display, 3000);
}
}Multiple toastMessage() calls targeting 'snackbar' are queued and shown one at a time, in order. Calls targeting 'inline' are all rendered concurrently by any <app-toast-message-display-inline> in the template.
Custom duration, bottom position
this.toastService.toastMessage(display, 5000, VerticalAlignment.BOTTOM);Manual dismiss only
this.toastService.toastMessage(display, 0);Inline display
this.toastService.toastMessage(display, 5000, undefined, 'inline');Reactive queue state
The service exposes its queue as computed signals, for anything that wants to observe it directly rather than only rendering via the provided components:
private toastService = inject(ToastMessageDisplayService);
readonly snackbarQueue = this.toastService.snackbarQueue; // ToastQueueEntry[], one shown at a time
readonly inlineToasts = this.toastService.inlineToasts; // ToastQueueEntry[], all shown concurrentlyComponents
<app-toast-message-display-inline>
Renders every toast currently targeted at 'inline', sourced automatically from the shared service - no input is needed to feed it toasts.
<app-toast-message-display-inline
[position]="'top'"
(close)="onClosedToast($event)"
></app-toast-message-display-inline>| Input | Type | Default | Description |
|------------|----------------------|---------|--------------|
| position | VerticalAlignment | 'top' | Layout position of the inline list |
| Output | Type | Description |
|---------|-------------------------|--------------|
| close | EventEmitter<ToastDisplay> | Emitted when a toast in the list is dismissed (auto-expiry or manual) |
Model Structures
ToastDisplay
export interface ToastDisplayInterface {
id?: string;
message: string;
action?: string; // button label; use '-' to render a close icon instead of text
color: ToastColors;
icon?: string;
}
const display = ToastDisplay.adapt({
message: 'Hello world!',
action: 'OK',
color: ToastColors.SUCCESS,
icon: 'check_circle'
});ToastColors
export enum ToastColors {
SUCCESS = "#006B31",
ERROR = "#CC0000",
INFO = "#02559F",
WARN = "#FFC20E",
NOTIFY = "#080808",
GENERAL = "#f5f5f5"
}VerticalAlignment
export enum VerticalAlignment {
TOP = "top",
BOTTOM = "bottom"
}ToastQueueEntry / ToastTarget
export type ToastTarget = 'snackbar' | 'inline';
export interface ToastQueueEntry {
toast: ToastDisplay;
target: ToastTarget;
vertical: VerticalAlignment;
durationMs: number;
expiresAt: number | null; // null while a snackbar entry is queued but not yet shown
}Best Practices
- Keep messages concise.
- Match color theme to message type (SUCCESS/ERROR/WARN/etc.).
- Use
duration: 0for anything the user must actively dismiss (e.g. an unresolved error), not a long auto-dismiss timeout. - Let the service handle sequencing for snackbar toasts - don't try to time calls to avoid overlap.
