Skip to content
Navigation

Toast

Transient, non-blocking feedback about something that already happened ("Saved", "Upload failed"). If the user MUST see or act on it, it is not a toast — use Notice (inline) or Dialog (blocking).

Added 14 October 2026

React

Codecomponents/react/toast-demo.tsx
import {Button, Toaster, toast} from '@stroeer-labs/design-library/react';

export function ToastDemo() {
    return (
        <div className="toast-scope">
            {/* Toast is imperative: mount <Toaster /> once, then call toast() from anywhere.
                toast-scope is a sandbox-only wrapper (see global.css) that pins the toaster inside
                this card so the React + Angular showcases don't collide on one page. It sits OUTSIDE
                the space-y-6 flow so sonner's (zero-height) section wrapper doesn't add a top gap. */}
            <Toaster />
            <div className="space-y-6">
                <div className="space-y-2">
                    <p className="text-xs font-medium text-muted-foreground">Types</p>
                    <div className="flex flex-wrap gap-3">
                        <Button variant="outline" onClick={() => toast('Event has been created')}>
                            Default
                        </Button>
                        <Button variant="outline" onClick={() => toast.success('Event has been created')}>
                            Success
                        </Button>
                        <Button variant="outline" onClick={() => toast.info('Be at the area 10 minutes before the event time')}>
                            Info
                        </Button>
                        <Button variant="outline" onClick={() => toast.warning('Event start time cannot be earlier than 8am')}>
                            Warning
                        </Button>
                        <Button variant="outline" onClick={() => toast.error('Event has not been created')}>
                            Error
                        </Button>
                    </div>
                </div>
                <div className="space-y-2">
                    <p className="text-xs font-medium text-muted-foreground">Description, action &amp; promise</p>
                    <div className="flex flex-wrap gap-3">
                        <Button
                            variant="outline"
                            onClick={() =>
                                toast('Event has been created', {
                                    description: 'Sunday, December 03, 2023 at 9:00 AM',
                                    action: {label: 'Undo', onClick: () => toast('Undone')},
                                })
                            }
                        >
                            With description
                        </Button>
                        <Button
                            variant="outline"
                            onClick={() =>
                                toast.promise<{name: string}>(() => new Promise((resolve) => setTimeout(() => resolve({name: 'Event'}), 2000)), {
                                    loading: 'Loading...',
                                    success: (data) => `${data.name} has been created`,
                                    error: 'Error',
                                })
                            }
                        >
                            Promise
                        </Button>
                    </div>
                </div>
            </div>
        </div>
    );
}

Angular

Codecomponents/angular/toast-demo.ts
import {Component} from '@angular/core';
import {HlmButtonImports, HlmToasterImports, toast} from '@stroeer-labs/design-library/angular';

@Component({
    selector: 'dl-toast-demo',
    standalone: true,
    imports: [HlmToasterImports, HlmButtonImports],
    template: `
        <div class="toast-scope">
            <!-- Toast is imperative: mount <hlm-toaster /> once, then call toast() from anywhere.
                 toast-scope is a sandbox-only wrapper (see global.css) that pins the toaster inside
                 this card so the React + Angular showcases don't collide on one page. It sits OUTSIDE
                 the space-y-6 flow to mirror the React demo structure exactly. -->
            <hlm-toaster />
            <div class="space-y-6">
                <div class="space-y-2">
                    <p class="text-xs font-medium text-muted-foreground">Types</p>
                    <div class="flex flex-wrap gap-3">
                        <button hlmBtn variant="outline" (click)="showDefault()">Default</button>
                        <button hlmBtn variant="outline" (click)="showSuccess()">Success</button>
                        <button hlmBtn variant="outline" (click)="showInfo()">Info</button>
                        <button hlmBtn variant="outline" (click)="showWarning()">Warning</button>
                        <button hlmBtn variant="outline" (click)="showError()">Error</button>
                    </div>
                </div>
                <div class="space-y-2">
                    <p class="text-xs font-medium text-muted-foreground">Description, action &amp; promise</p>
                    <div class="flex flex-wrap gap-3">
                        <button hlmBtn variant="outline" (click)="showDescription()">With description</button>
                        <button hlmBtn variant="outline" (click)="showPromise()">Promise</button>
                    </div>
                </div>
            </div>
        </div>
    `,
})
export class ToastDemoComponent {
    showDefault() {
        toast('Event has been created');
    }

    showSuccess() {
        toast.success('Event has been created');
    }

    showInfo() {
        toast.info('Be at the area 10 minutes before the event time');
    }

    showWarning() {
        toast.warning('Event start time cannot be earlier than 8am');
    }

    showError() {
        toast.error('Event has not been created');
    }

    showDescription() {
        toast('Event has been created', {
            description: 'Sunday, December 03, 2023 at 9:00 AM',
            action: {label: 'Undo', onClick: () => toast('Undone')},
        });
    }

    showPromise() {
        toast.promise<{name: string}>(() => new Promise((resolve) => setTimeout(() => resolve({name: 'Event'}), 2000)), {
            loading: 'Loading...',
            success: (data) => `${data.name} has been created`,
            error: 'Error',
        });
    }
}