[ Installation ]

npx wally-ui add toast

[ Setup ]

Add the Toast component once at the root level of your application.

// app.component.ts
import { Component } from '@angular/core';
import { Toast } from './components/wally-ui/toast/toast';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  imports: [Toast, RouterOutlet],
  template: `
    <!-- Add toast container once at root level -->
    <wally-toast />

    <!-- Rest of your app -->
    <router-outlet />
  `
})
export class AppComponent {}

[ Basic Usage ]

// In any component
import { ToastService } from './components/wally-ui/toast/lib/services/toast.service';

export class ExampleComponent {
  private toastService = inject(ToastService);

  showToast() {
    this.toastService.create({
      type: 'success',
      message: 'Operation completed successfully!'
    });
  }
}

[ All Types ]

[ Types ]

Success

For successful operations, confirmations, and positive feedback.

this.toastService.create({
  type: 'success',
  title: 'Success!',
  message: 'Your changes have been saved.'
});

Error

For errors, failures, and critical issues that need attention.

this.toastService.create({
  type: 'error',
  title: 'Error',
  message: 'Something went wrong. Please try again.'
});

Info

For informational messages and general notifications.

this.toastService.create({
  type: 'info',
  title: 'Info',
  message: 'You have 3 unread notifications.'
});

Warning

For warnings, cautions, and potential issues.

this.toastService.create({
  type: 'warning',
  title: 'Warning',
  message: 'Your session will expire in 5 minutes.'
});

Loading

For async operations. Loading toasts don't auto-dismiss and must be removed manually.

// Loading toast (no auto-dismiss)
const loadingToastId = this.toastService.create({
  type: 'loading',
  message: 'Processing your request...'
});

// Later, remove it manually
setTimeout(() => {
  this.toastService.remove(loadingToastId);
}, 3000);

Neutral

For generic notifications without an icon. Neutral toasts don't auto-dismiss and must be removed manually.

// Neutral toast (no icon, no auto-dismiss)
const neutralToastId = this.toastService.create({
  type: 'neutral',
  title: 'Information',
  message: 'This is a neutral toast without an icon.'
});

// Later, remove it manually
setTimeout(() => {
  this.toastService.remove(neutralToastId);
}, 3000);

[ Positions ]

Toasts can be positioned in 9 different locations. Default position is top-center.

Top Positions

Center Positions

Bottom Positions

[ Stacking & Hover Expansion ]

Maximum 5 toasts per position. New toasts appear on top with subtle stacking effect. Hover to expand and see all toasts.

// Demonstrate stacking behavior
showMultipleToasts() {
  // Create 5 toasts to see stacking
  for (let i = 1; i <= 5; i++) {
    setTimeout(() => {
      this.toastService.create({
        type: 'info',
        title: `Toast #${i}`,
        message: `This is toast number ${i}`,
        duration: 10000
      });
    }, i * 500); // Stagger by 500ms
  }
}

[ Production Examples ]

Form Submission

// Form submission example
export class LoginComponent {
  private toastService = inject(ToastService);

  async onSubmit() {
    const loadingId = this.toastService.create({
      type: 'loading',
      message: 'Signing in...'
    });

    try {
      await this.authService.login(this.credentials);

      // Remove loading toast
      this.toastService.remove(loadingId);

      // Show success
      this.toastService.create({
        type: 'success',
        title: 'Welcome back!',
        message: 'You have successfully signed in.'
      });
    } catch (error) {
      // Remove loading toast
      this.toastService.remove(loadingId);

      // Show error
      this.toastService.create({
        type: 'error',
        title: 'Login failed',
        message: error.message
      });
    }
  }
}

File Upload

// File upload with progress
export class UploadComponent {
  private toastService = inject(ToastService);

  async uploadFile(file: File) {
    const uploadingId = this.toastService.create({
      type: 'loading',
      message: 'Uploading file...'
    });

    try {
      await this.fileService.upload(file);

      this.toastService.remove(uploadingId);
      this.toastService.create({
        type: 'success',
        title: 'Upload complete',
        message: `${file.name} has been uploaded successfully.`
      });
    } catch (error) {
      this.toastService.remove(uploadingId);
      this.toastService.create({
        type: 'error',
        title: 'Upload failed',
        message: 'Failed to upload file. Please try again.'
      });
    }
  }
}

Clipboard Copy

// Clipboard copy feedback
export class CodeExampleComponent {
  private toastService = inject(ToastService);

  async copyToClipboard(text: string) {
    try {
      await navigator.clipboard.writeText(text);

      this.toastService.create({
        type: 'success',
        message: 'Copied to clipboard!',
        duration: 2000,
        position: 'bottom-center'
      });
    } catch (error) {
      this.toastService.create({
        type: 'error',
        message: 'Failed to copy',
        duration: 2000
      });
    }
  }
}

[ API Reference ]

Toast Properties

Property Type Default Description
type 'success' | 'error' | 'info' | 'warning' | 'loading' | 'neutral' required Visual type and icon of the toast. Loading and neutral have no auto-dismiss
message string required Main message text displayed in the toast
title string undefined Optional bold title text displayed above the message
duration number 5000 Auto-dismiss duration in milliseconds. Set to 0 for no auto-dismiss (manual close only)
position ToastPosition 'top-center' Position on screen: 'top-left', 'top-center', 'top-right', 'center-left', 'center', 'center-right', 'bottom-left', 'bottom-center', 'bottom-right'

ToastService Methods

Method Parameters Returns Description
create() toast: Omit<Toast, 'id'> number Creates and displays a new toast. Returns the toast ID for manual removal (required for loading toasts)
remove() id: number void Removes a toast by ID. Use this to manually dismiss loading or neutral toasts
pause() id: number void Pauses auto-dismiss timer (used internally on hover). Calculates remaining time for accurate resume
resume() id: number void Resumes auto-dismiss timer with remaining duration (used internally when hover ends)
setDefaultPosition() position: ToastPosition void Sets the default position for all future toasts. Call during app initialization

Usage Examples

create()

// ToastService.create() method signature
create(toast: {
  type: 'success' | 'error' | 'info' | 'warning' | 'loading' | 'neutral';
  message: string;
  title?: string;
  duration?: number; // milliseconds (default: 5000, 0 for no auto-dismiss)
  position?: ToastPosition; // default: 'top-center'
}): number; // Returns toast ID

remove()

// ToastService.remove() method signature
remove(id: number): void;

// Example
const toastId = this.toastService.create({
  type: 'loading',
  message: 'Loading...'
});

// Remove it later
this.toastService.remove(toastId);

setDefaultPosition()

// ToastService.setDefaultPosition() method signature
setDefaultPosition(position: ToastPosition): void;

// Example
this.toastService.setDefaultPosition('bottom-right');

Type Definitions

// Available types
export type ToastType = 'success' | 'error' | 'info' | 'warning' | 'loading' | 'neutral';

export type ToastPosition =
  | 'top-left' | 'top-center' | 'top-right'
  | 'center-left' | 'center' | 'center-right'
  | 'bottom-left' | 'bottom-center' | 'bottom-right';

export interface Toast {
  id: number;
  type: ToastType;
  title?: string;
  message: string;
  duration?: number;
  position?: ToastPosition;
}

Last updated: 2026