Installation

Start in 3 minutes

Install the library

Run this command in your terminal, inside your Angular project:

Terminal
npm install ng-toastly

πŸ’‘ What does this do?

Add the container

The container is where toasts appear. Add it to your main component:

app.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ToastContainerComponent } from 'toastly';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet, ToastContainerComponent],
  template: `
    <router-outlet />
    <toastly-container />
  `,
})
export class AppComponent {}

πŸ€” Why in the main component?

Optional

Add @import 'toastly/styles/toastly.css'; to your styles.css

styles.css
@import 'toastly/styles/toastly.css';

πŸŽ‰ Done!

Automatic Setup with ng add

The fastest way to add ng-toastly to your project.

What is ng add?

ng add is an official Angular CLI command that allows libraries to automatically configure your project.

ng-toastly uses this feature to save you time and prevent common setup mistakes.

How to Use

Simply run this command in your Angular project:

Terminal
ng add ng-toastly

βœ… Safe to run: This command only adds what's needed.

βœ… Run once: If you run it again, it will skip what's already configured.

What Gets Configured

The schematic automatically:

  • βœ… Adds provideToastly() to your app configuration
  • βœ… Adds toastly-container to your AppComponent
  • βœ… Detects if your project uses standalone or NgModule
  • βœ… Avoids duplicating code if already configured
  • βœ… Shows clear messages about what was changed

What It Does NOT Do

By design, the schematic does not:

  • ❌ Set a specific theme (light/dark)
  • ❌ Configure language or i18n
  • ❌ Modify your app's styles or layout
  • ❌ Add unnecessary dependencies

Why? These decisions belong to your application, not to the library.

Why Use a Schematic?

  • Reduces setup time β€” No manual file editing required
  • Prevents mistakes β€” Correct configuration every time
  • Improves DX β€” Better developer experience from the start
  • Keeps code clean β€” Adds only what's necessary

Safety & Best Practices

  • πŸ”’ Idempotent: Running twice won't duplicate anything
  • πŸ” Respects structure: Works with your existing setup
  • πŸ“ Clear feedback: Terminal messages explain what changed

Available Options

You can customize the schematic with options:

Terminal
# Set default position
ng add ng-toastly --position=top-right

# Skip container (add manually)
ng add ng-toastly --skipContainer
Option Description
--position Set default toast position
--skipContainer Skip adding the container

Show your first toast!

Use the ToastService in any component to show notifications:

Getting Started

my-component.ts
import { Component, inject } from '@angular/core';
import { ToastService } from 'toastly';

@Component({
  selector: 'app-my-component',
  template: `
    <button (click)="showToast()">
      Click me!
    </button>
  `,
})
export class MyComponent {
  // Step 1: Inject the service
  private readonly toastService = inject(ToastService);

  showToast(): void {
    // Step 2: Use service to show a toast
    this.toastService.success('It worked! πŸŽ‰');
  }
}

Understanding the code line by line:

Line What it does
inject(ToastService) Gets an instance of the toast service.
private readonly private: only this component...
.success() Shows a "success" toast...

Toast Types

Choose a type to preview

ℹ️

Info

Info

toastService.info('Info message');
βœ…

Success

Success

toastService.success('Success message');
⚠️

Warning

Warning

toastService.warning('Warning message');
❌

Danger

Danger

toastService.danger('Error message');
βœ… Do

Reserve success for important actions

Available Options

Description

Try different configurations
toastService.show({
  // Required
  message: 'Your message here',
  
  // Optional
  title: 'Toast Title',
  type: 'success',        // 'info' | 'success' | 'warning' | 'danger'
  theme: 'dark',          // 'light' | 'dark'
  durationMs: 8000,       // Time in ms
  dismissible: true,     // Show close button
  styleClass: 'my-class',
});

Options

Option Type Default Description
message string - Message text
title string - Bold title above the message
type 'info' | 'success' | 'warning' | 'danger' 'info' Defines the color and icon
theme 'light' | 'dark' 'light' Visual theme (light or dark)
durationMs number 5000 Time to close automatically (0 = never)
dismissible boolean true Whether to show the close (x) button
styleClass string - Custom CSS classes
progressPercent number - Progress bar value (0-100)

Positioning

Position Demo

Positions

top-left ↖️ Top Left
top-center ⬆️ Top Center
top-right ↗️ Top Right
bottom-left ↙️ Bottom Left
bottom-center ⬇️ Bottom Center
bottom-right β†˜οΈ Bottom Right

How to change position

<toastly-container position="top-right" />

Action Buttons

Dark theme... pairs well with toasts that have action buttons.

toastService.show({
  type: 'info',
  theme: 'dark',
  title: 'Update Available',
  message: 'Version 4.2 available',
  durationMs: 0, // No auto close
  actions: [
    {
      label: 'Skip',
      variant: 'secondary',
      onClick: () => this.skip(),
    },
    {
      label: 'Install',
      variant: 'primary',
      onClick: () => this.install(),
    },
  ],
});

CSS Variables

CSS variables for everything...

/* Customize global look */
:root {
  --toastly-bg: #ffffff;
  --toastly-success: #16a34a;
}

Custom CSS Classes

For granular control, apply custom CSS classes.

1. Define your class in global styles:

styles.css
.my-gold-toast {
  /* Override variables or properties */
  --toastly-bg: #ffd700;
  --toastly-text: #000000;
  border: 2px solid #b8860b;
  font-weight: bold;
}

2. Use the class when showing a toast:

component.ts
this.toastService.show({
  message: 'You won a prize! πŸ†',
  styleClass: 'my-gold-toast'
});

Note: Use styles.css or ::ng-deep.

Custom Icons

Use your own icons...

How does it work?

Toastly accepts a TemplateRef...

1. Install Lucide Angular

npm install lucide-angular

2. Create a template for the icon

In your component...

<!-- Custom icon template -->
<ng-template #customIcon>
  <!-- Reference to Lucide icons -->
  <i-lucide name="download"></i-lucide>
</ng-template>
πŸ€” Why use TemplateRef?

Using TemplateRef...

Using direct SVG (no library)

If you do not want to install an icon library...

<ng-template #svgIcon>
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" ...>
    <path d="..." />
  </svg>
</ng-template>

Different icons for each type

You can create a service...

πŸ’‘ Style Tip

Default icons use width: 20px...

Themes

Light or Dark...

Comparison

// Light theme (default)

βœ…
Success
Operation completed

// Dark theme

βœ…
Success
Operation completed
πŸ’‘ When to use dark theme?

Dark theme is great for...

Custom Animations

Toastly animations are designed to be smooth and unobtrusive...

Animation Presets

We provide built-in presets for common use cases:

  • animationPreset: 'slide' - Slide (Default)
  • animationPreset: 'fade' - Fade
  • animationPreset: 'bounce' - Bounce
app.config.ts
provideToastly({
  animationPreset: 'bounce', // 'slide' | 'fade' | 'bounce'
  position: 'top-right'
});

Custom Animations via Callback

For full control...

Toastly waits...

app.config.ts
provideToastly({
  animation: {
    // Called when toast is created
    enter: (element: HTMLElement) => {
      // Use Web Animations API
      element.animate(
        [
          { transform: 'translateX(100%)', opacity: 0 },
          { transform: 'translateX(0)', opacity: 1 }
        ],
        { duration: 300, easing: 'ease-out', fill: 'forwards' }
      );
    },
    // Called when toast is dismissed
    leave: (element: HTMLElement) => {
      return element.animate(
        [
          { opacity: 1 },
          { opacity: 0, transform: 'scale(0.9)' }
        ],
        { duration: 200, easing: 'ease-in', fill: 'forwards' }
      );
    }
  }
});

Customization with CSS Variables

You can tweak speed and easing using CSS variables:

styles.css
:root {
  /* Default: 300ms */
  --toastly-animation-duration: 500ms;
  
  /* Default: cubic-bezier(...) */
  --toastly-animation-easing: ease-in-out;
}

Accessibility

Accessibility

Toastly respects prefers-reduced-motion...

Best Practices

  • βœ… Keep animations short...
  • βœ… Use ease-out...
  • ❌ Don't use complex animations...
  • ❌ Don't block dismissal...

Global Configuration

Set default values for all toasts in your application.

How to Configure

Use provideToastly() in your application configuration:

app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideToastly } from 'ng-toastly';

export const appConfig: ApplicationConfig = {
  providers: [
    provideToastly({
      position: 'top-right',
      theme: 'dark',
      defaultDurationMs: 3000,
      dismissibleByDefault: true,
      newestOnTop: true,
    }),
  ],
};

Available Options

Option Type Default Description
position ToastPosition 'bottom-right' Default position for all toasts
theme 'light' | 'dark' 'light' Default theme for all toasts
defaultDurationMs number 5000 Auto-dismiss delay in milliseconds
maximumVisibleToasts number 5 Max toasts visible at once
newestOnTop boolean true New toasts appear at top of stack
pauseOnHover boolean true Pause auto-dismiss on hover
dismissibleByDefault boolean true Show close button by default
defaultType ToastType 'info' Default toast type when not specified

Manual Configuration (Alternative)

You can also provide configuration directly using the injection token:

app.config.ts
import { TOAST_GLOBAL_CONFIG } from 'ng-toastly';

export const appConfig = {
  providers: [
    {
      provide: TOAST_GLOBAL_CONFIG,
      useValue: {
        position: 'top-center',
        theme: 'dark',
      },
    },
  ],
};

Best Practices

βœ… Do

  • Use short and direct messages
  • Reserve success for important actions
  • Use warning before destructive actions
  • Allow user to dismiss manually
  • Increase duration for long messages

❌ Avoid

  • Toasts for every small action
  • Very long messages
  • More than 3 toasts at once
  • Toasts that cannot be dismissed
  • Using danger for simple validation errors

Common Errors

Toast does not appear

Cause: Forgot container

Solution: Add container

Technical Decisions

Why Signals?

We use Angular's Signals API because:

  • Performance...
  • Simplicity...
  • Future...
  • Fewer bugs...

Why zero dependencies?

We decided not to use...

  • Fewer conflicts...
  • Smaller bundle...
  • Maintenance...
  • Control...

Why "simple" code?

Toastly code is intentionally simple...

  • Readability...
  • Debugging...
  • Learning...
  • Maintenance...
"Prefer code..."

Why DestroyRef for timers?

We use DestroyRef...

  • Prevents memory leaks
  • Avoids errors...
  • Modern standard...