Feedback
Toast
Usage#
import { WdsToasterComponent } from '@wds/angular/toast';Examples#
Default#
toast() shows a notification and returns its id. It uses the <wds-toaster> on the page, or adds one when there is none; in an app, put one <wds-toaster> in the root layout. In Angular import toast from @wds/angular/toast, elsewhere from @wds/core/toast.
import { Component } from '@angular/core';
import { WdsButtonComponent } from '@wds/angular/button';
import { toast } from '@wds/angular/toast';
@Component({
selector: 'app-toast-default-demo',
imports: [WdsButtonComponent],
template: `
<div class="flex flex-wrap justify-center gap-2">
<wds-button variant="outline" (click)="showToast()">Show toast</wds-button>
</div>
`,
})
export class ToastDefaultDemo {
protected showToast(): void {
toast('Event has been created', {
description: 'Sunday, December 03, 2023 at 9:00 AM',
action: { label: 'Undo', onClick: () => toast('Event removed') },
});
}
}Types#
toast.success, info, warning, error and loading add an icon. toast.promise shows a loading toast that turns into success or error when the promise settles.
import { Component } from '@angular/core';
import { WdsButtonComponent } from '@wds/angular/button';
import { toast } from '@wds/angular/toast';
@Component({
selector: 'app-toast-types-demo',
imports: [WdsButtonComponent],
template: `
<div class="flex flex-wrap justify-center gap-2">
<wds-button variant="outline" (click)="showDefault()">Default</wds-button>
<wds-button variant="outline" (click)="showSuccess()">Success</wds-button>
<wds-button variant="outline" (click)="showInfo()">Info</wds-button>
<wds-button variant="outline" (click)="showWarning()">Warning</wds-button>
<wds-button variant="outline" (click)="showError()">Error</wds-button>
<wds-button variant="outline" (click)="showPromise()">Promise</wds-button>
</div>
`,
})
export class ToastTypesDemo {
protected showDefault(): void {
toast('Changes saved');
}
protected showSuccess(): void {
toast.success('Message sent', { description: 'The recipient will get it in a moment.' });
}
protected showInfo(): void {
toast.info('A new version is available', { description: 'Reload the page to load it.' });
}
protected showWarning(): void {
toast.warning('Low disk space', { description: '512 MB left.' });
}
protected showError(): void {
toast.error('Could not save', { description: 'Check your connection and try again.' });
}
protected showPromise(): void {
const save = new Promise<{ name: string }>((resolve) => setTimeout(() => resolve({ name: 'Q3 report' }), 1500));
toast.promise(save, {
loading: 'Saving…',
success: (data) => `Saved “${data.name}”`,
error: 'Could not save',
});
}
}Action and cancel#
action and cancel add buttons; both close the toast unless onClick calls event.preventDefault(). duration sets the time in ms.
import { Component } from '@angular/core';
import { WdsButtonComponent } from '@wds/angular/button';
import { toast } from '@wds/angular/toast';
@Component({
selector: 'app-toast-action-cancel-demo',
imports: [WdsButtonComponent],
template: `
<div class="flex flex-wrap justify-center gap-2">
<wds-button variant="outline" (click)="deleteFile()">Delete file</wds-button>
<wds-button variant="outline" (click)="invite()">Invitation</wds-button>
</div>
`,
})
export class ToastActionCancelDemo {
protected deleteFile(): void {
toast('File moved to trash', {
action: { label: 'Undo', onClick: () => toast.success('File restored') },
});
}
protected invite(): void {
toast('Anna invited you to a project', {
description: 'Project “New website”',
cancel: { label: 'Decline' },
action: { label: 'Join', onClick: () => toast.success('Joined the project') },
duration: 8000,
});
}
}Update and dismiss#
id updates that toast. duration: Infinity keeps it until it is closed; toast.dismiss(id) closes one toast and toast.dismiss() all of them.
import { Component } from '@angular/core';
import { WdsButtonComponent } from '@wds/angular/button';
import { toast } from '@wds/angular/toast';
@Component({
selector: 'app-toast-update-dismiss-demo',
imports: [WdsButtonComponent],
template: `
<div class="flex flex-wrap justify-center gap-2">
<wds-button variant="outline" (click)="upload()">Upload file</wds-button>
<wds-button variant="outline" (click)="sticky()">No time limit</wds-button>
<wds-button variant="ghost" (click)="dismissAll()">Dismiss all</wds-button>
</div>
`,
})
export class ToastUpdateDismissDemo {
protected upload(): void {
// A toast with the same id replaces the previous one.
const id = toast.loading('Uploading file…');
setTimeout(() => toast.success('File uploaded', { id, description: 'report.pdf, 2.4 MB' }), 2000);
}
protected sticky(): void {
toast('This notification stays', { description: 'Close it with the button or a swipe.', duration: Infinity });
}
protected dismissAll(): void {
toast.dismiss();
}
}Position#
position places the toaster in a corner or at the center of an edge. A toaster with an id gets only the toasts whose toaster option names it, so it can sit next to the default one; give it its own label.
import { Component, signal } from '@angular/core';
import { WdsButtonComponent } from '@wds/angular/button';
import { WdsToasterComponent, toast } from '@wds/angular/toast';
import type { WdsToasterPosition } from '@wds/core/toast';
@Component({
selector: 'app-toast-position-demo',
imports: [WdsButtonComponent, WdsToasterComponent],
template: `
<!-- A second toaster: toasts reach it through the toaster option (its id). -->
<wds-toaster id="position-toaster" label="Positioned notifications" [position]="position()" />
<div class="flex flex-wrap justify-center gap-2">
@for (p of positions; track p) {
<wds-button variant="outline" size="sm" (click)="show(p)">{{ p }}</wds-button>
}
</div>
`,
})
export class ToastPositionDemo {
protected readonly positions: WdsToasterPosition[] = ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'];
protected readonly position = signal<WdsToasterPosition>('bottom-right');
protected show(position: WdsToasterPosition): void {
this.position.set(position);
toast('Event has been created', { description: `Shown at ${position}.`, toaster: 'position-toaster' });
}
}Options#
rich-colors colors success, info, warning and error toasts; expand keeps the stack expanded; hide-close hides the close button (a swipe still closes the toast).
import { Component, signal } from '@angular/core';
import { WdsButtonComponent } from '@wds/angular/button';
import { WdsSwitchComponent } from '@wds/angular/switch';
import { WdsToasterComponent, toast } from '@wds/angular/toast';
@Component({
selector: 'app-toast-options-demo',
imports: [WdsButtonComponent, WdsSwitchComponent, WdsToasterComponent],
template: `
<wds-toaster id="options-toaster" label="Notifications with options" [richColors]="richColors()" [expand]="expand()" [hideClose]="hideClose()" />
<div class="flex flex-col items-center gap-4">
<div class="flex flex-wrap justify-center gap-4">
<wds-switch [checked]="richColors()" (wdsChange)="richColors.set($event.checked)">Rich colors</wds-switch>
<wds-switch [checked]="expand()" (wdsChange)="expand.set($event.checked)">Expand</wds-switch>
<wds-switch [checked]="hideClose()" (wdsChange)="hideClose.set($event.checked)">Hide close</wds-switch>
</div>
<div class="flex flex-wrap justify-center gap-2">
<wds-button variant="outline" (click)="success()">Success</wds-button>
<wds-button variant="outline" (click)="error()">Error</wds-button>
</div>
</div>
`,
})
export class ToastOptionsDemo {
protected readonly richColors = signal(true);
protected readonly expand = signal(false);
protected readonly hideClose = signal(false);
protected success(): void {
toast.success('Message sent', { description: 'The recipient will get it in a moment.', toaster: 'options-toaster' });
}
protected error(): void {
toast.error('Could not save', { description: 'Check your connection and try again.', toaster: 'options-toaster' });
}
}API References#
wds-toaster#
toast() function adds them.
The stack expands on hover and focus, alt+T moves focus to the notifications,
and a swipe closes a toast. The timer pauses while the user interacts with them.
It is shown in the top layer, above lists and menus.
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| position | WdsToasterPosition | 'bottom-right' | |
| expand | boolean | false | |
| rich-colors.richColors | boolean | false | |
| hide-close.hideClose | boolean | false | |
| duration | number | 4000 | |
| visible-toasts.visibleToasts | number | 3 | |
| gap | number | 12 | |
| label | string | 'Powiadomienia' | |
| close-label.closeLabel | string | 'Zamknij powiadomienie' |
Methods
| Method | Description |
|---|---|
| add(toast: WdsToast) | toast(). |
| dismiss(id?: string | number) |
CSS parts (::part)
| Part | Description |
|---|---|
| list | |
| toast | |
| close |
CSS custom properties
| Property | Description |
|---|---|
| --wds-toaster-width | |
| --wds-toaster-offset |
Accessibility#
Screen reader#
label (default Powiadomienia, in Polish) with a hint about alt+T. It exists before the first toast, so screen readers announce new toasts.
role="status" (announced politely) or, for toast.error, role="alert" (announced at once); aria-atomic reads the title and the description together. Icons are hidden from screen readers.
label. The close button is named by close-label (default Zamknij powiadomienie, in Polish).
Keyboard support#
| Key | Function |
|---|---|