npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

toast-vanilla

v1.0.6

Published

A lightweight, vanilla JavaScript toast notification system with zero dependencies. Display elegant notifications with support for standard toasts and promise-based async operations.

Readme

Toast Vanilla

A lightweight, vanilla JavaScript toast notification system with zero dependencies. Display elegant notifications with support for standard toasts and promise-based async operations.

Features

  • No Dependencies - Pure vanilla JavaScript
  • Accessible - Built with ARIA labels and semantic HTML
  • Performant - Lightweight and efficient DOM manipulation
  • Highly Customizable - Control every aspect including colors, spacing, positioning, duration, and variants
  • Design System Integration - Seamlessly integrate with shadcn/ui and other design systems using CSS variables
  • Multiple Toast Types - Success, error, warning, info, and loader states
  • Promise Support - Automatic loading, success, and error state management

Installation using NPM

npm install toast-vanilla

Quick Start

import { ToastVanilla } from 'toast-vanilla';

// Initialize the toast system
const toast = new ToastVanilla({
  maxItemToRender: 3,
  position: 'top-right',
  duration: 3000,
});

// Show notifications
toast.success('Operation completed!');
toast.error('Something went wrong');
toast.warn('Please review this');
toast.info('Here's some information');

Quick Start using CDN

  1. Include the Stylesheet Add the CSS file to your HTML tag
<link
  rel="stylesheet"
  href="https://unpkg.com/[email protected]/dist/index.min.css"
/>
  1. Initialize Toast Vanilla Add a module script to initialize the toast instance and make it globally available:
<script type="module">
  import { ToastVanilla } from 'https://unpkg.com/[email protected]/dist/index.min.js';

  window.toast = new ToastVanilla({
    position: 'bottom-left',
    maxItemToRender: 3,
    duration: 3000,
    styles: {
      background: 'var(--card)',
      primaryTextColor: 'var(--primary)',
      primaryTextColorForeground: 'var(--primary-foreground)',
      secondaryTextColor: 'var(--secondary)',
      secondaryTextColorForeground: 'var(--secondary-foreground)',
      border: 'var(--border)',
    },
  });
</script>
  1. Use it Anywhere Once initialized, you can call toast methods from any script on your page:
<script>
  // Success notification
  window.toast.success('Operation successful!');

  // Error notification
  window.toast.error('Something went wrong!');

  // Warning notification
  window.toast.warn('Please be careful!');

  // Info notification
  window.toast.info('Here is some information');

  // Promise-based toast
  window.toast.promise(() => fetch('/api/data').then((res) => res.json()), {
    loading: 'Loading data...',
    success: (data) => `Data loaded: ${data.count} items`,
    error: (err) => `Failed to load: ${err.message}`,
  });
</script>

NOTE: Make sure the module script runs before you try to use window.toast in other scripts

Configuration

Initialize ToastVanilla with a configuration object:

const toast = new ToastVanilla({
  maxItemToRender: 3, // Maximum visible toasts
  position: 'top-right', // top-left, top-right, bottom-left, bottom-right
  duration: 3000, // Auto-dismiss time in milliseconds
  styles: {
    // Custom styling (optional)
    borderRadius: 8,
    gap: 16,
    background: '#ffffff',
    // ... more style options
  },
});

Position Options

  • top-left
  • top-right
  • bottom-left
  • bottom-right

API

Standard Toasts

success(message, options?)

Display a success notification.

toast.success('File uploaded successfully', {
  title: 'Upload Complete',
  duration: 3000,
  variant: 'filled',
});

error(message, options?)

Display an error notification.

toast.error('Failed to upload file', {
  title: 'Upload Failed',
  variant: 'outline',
});

warn(message, options?)

Display a warning notification.

toast.warn('This action cannot be undone', {
  title: 'Warning',
});

info(message, options?)

Display an info notification.

toast.info('Your session will expire soon', {
  title: 'Reminder',
});

Promise-Based Toasts

Simple example of promise toast with AbortController

const controller = new AbortController();

await toast.promise(
  async () => {
    // Your async operation
    const response = await fetch('/api/data', { signal: controller.signal });
    return response.json();
  },
  {
    loading: 'Loading data...',
    success: (data) => `Loaded ${data.items} items`,
    error: (err) => `Failed: ${err.message}`,
    dissmissable: true,
    onDismissCallback: () => controller.abort(),
  },
);

Options

Toast Options

| Option | Type | Default | Description | Use Case | | ------------- | -------------------------------------------------------------- | ------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------- | | title | string | 'Title' | The heading text displayed in the toast | Provide context about the notification type (e.g., "Success", "Error") | | duration | number | 3000 | Time in milliseconds before the toast auto-dismisses | Longer for important info, shorter for quick confirmations | | variant | 'outline' \| 'filled' \| 'default' | 'default' | Visual style of the toast | outline for subtle notifications, filled for emphasis, default for balance | | dismissable | boolean | 'true' | Allows user to dismiss the toast by clicking an X button | Disable for critical toasts to ensure users read the message before it auto-dismisses | | position | 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' | 'top-right' | Where toasts appear on screen | Position based on UI layout and user attention flow | | showIcon | boolean | true | Include icon to the toast elemennt | Hide icon to highlight notification message |

Promise Options

| Option | Type | Required | Description | Use Case | | ------------------- | -------------------------- | -------- | --------------------------------------------------------- | ------------------------------------------------------------------------------- | | loading | string | ✓ | Message displayed while the promise is pending | Show user the operation is in progress (e.g., "Uploading file...") | | success | (data: T) => string | ✓ | Function that returns success message from promise result | Display result data (e.g., (data) => 'Uploaded 5 files') | | error | (error: Error) => string | ✓ | Function that returns error message from the error object | Show helpful error info (e.g., (err) => 'Failed: ${err.message}') | | duration | number | ✗ | Time before toast dismisses after completion | Override default duration for specific operations | | onDismissCallback | ()=>void | ✗ | A callback on dismissing toast | Promise cleanup callback e.g. fetching in the API with AbortController clean up | | dismissable | boolean | ✗ | Allows user to dismiss the toast by clicking an X button | Disable for important promise operation |

Configuration Options

| Option | Type | Default | Description | Use Case | | ----------------- | -------------------------------------------------------------- | ------------- | ----------------------------------------- | ------------------------------------------------------ | | position | 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' | 'top-right' | Where toasts appear on screen | Position based on UI layout and user attention flow | | maxItemToRender | number | 3 | Maximum number of visible toasts at once | Prevent toast overflow; use 1-5 based on screen size | | duration | number | 3000 | Default auto-dismiss time in milliseconds | Adjust based on message complexity (2000-5000 typical) | | styles | ToastStyle | {} | Custom colors and dimensions | Override defaults or integrate with design system |

Style Options

Layout & Spacing

| Property | Type | Default | Description | Use Case | | -------------- | -------- | ------- | ---------------------------------------- | ---------------------------------------- | | offset | number | 16 | Distance in pixels from screen edges | Increase for mobile-safe spacing | | borderRadius | number | 8 | Corner radius in pixels | Match your design system's border radius | | gap | number | 16 | Spacing between stacked toasts in pixels | Increase for more visual separation |

Background & Border

| Property | Type | Default | Description | Use Case | | ------------ | -------- | ---------------------------------- | ------------------------------------------ | --------------------------------------- | | background | string | 'oklch(1 0 0)' | Toast background color (default & outline) | White or light backgrounds for contrast | | border | string | 'oklch(95.514% 0.00011 271.152)' | Border color (outline variant) | Subtle gray border for definition |

Status Colors

| Property | Type | Default | Description | Use Case | | -------------- | -------- | ------------------------------ | ----------------------- | ---------------------------------- | | successColor | string | 'oklch(0.627 0.194 149.214)' | Success indicator color | Green-tinted for positive feedback | | errorColor | string | 'oklch(0.577 0.245 27.325)' | Error indicator color | Red-tinted for errors | | warningColor | string | 'oklch(0.705 0.213 47.604)' | Warning indicator color | Orange-tinted for caution | | infoColor | string | 'oklch(0.546 0.245 262.881)' | Info indicator color | Blue-tinted for information |

Text Colors (Default & Outline Variants)

| Property | Type | Default | Description | Use Case | | -------------------- | -------- | ------------------------------ | ------------------ | -------------------------------------- | | primaryTextColor | string | 'oklch(0.141 0.005 285.823)' | Title text color | Dark for high contrast and readability | | secondaryTextColor | string | 'oklch(0.21 0.006 285.885)' | Message text color | Slightly lighter than primary text |

Text Colors (Filled Variant)

| Property | Type | Default | Description | Use Case | | ------------------------------ | -------- | -------------------- | ---------------------------------------- | ---------------------------------------------- | | primaryTextColorForeground | string | 'oklch(1 0 0)' | Title text color on colored background | White/light text for filled backgrounds | | secondaryTextColorForeground | string | 'oklch(0.985 0 0)' | Message text color on colored background | Off-white for secondary text in filled variant |

Icon Stroke (Default & Outline Variants)

| Property | Type | Default | Description | Use Case | | ------------- | -------- | ---------------- | ----------------------------------- | -------------------------- | | strokeColor | string | 'oklch(1 0 0)' | Icon stroke color (default variant) | White for thin icon lines | | fillColor | string | 'oklch(1 0 0)' | Icon fill color (default variant) | White for solid icon areas |

Icon Stroke (Filled Variant)

| Property | Type | Default | Description | Use Case | | ----------------------- | -------- | -------------------- | --------------------------------------- | -------------------------------------------- | | strokeColorForeground | string | 'oklch(0.985 0 0)' | Icon stroke color on colored background | Light color for contrast on dark backgrounds |

Complete Style Configuration Example

const toast = new ToastVanilla({
  styles: {
    // Layout
    offset: 16,
    borderRadius: 8,
    gap: 16,

    // Colors - Default & Outline
    background: '#ffffff',
    border: '#e5e7eb',

    // Status Colors
    successColor: '#10b981',
    errorColor: '#ef4444',
    warningColor: '#f59e0b',
    infoColor: '#3b82f6',

    // Text - Default & Outline
    primaryTextColor: '#1f2937',
    secondaryTextColor: '#6b7280',

    // Text - Filled Variant
    primaryTextColorForeground: '#ffffff',
    secondaryTextColorForeground: '#f3f4f6',

    // Icons - Default & Outline
    strokeColor: '#ffffff',
    fillColor: '#ffffff',

    // Icons - Filled Variant
    strokeColorForeground: '#fafafa',
  },
});

Styling

Customize the appearance with the styles configuration:

const toast = new ToastVanilla({
  styles: {
    offset: 16, // Distance from viewport edge
    borderRadius: 8, // Corner radius
    gap: 16, // Space between toasts
    background: '#ffffff', // Toast background
    border: '#e5e7eb', // Border color
    successColor: 'oklch(0.627 0.194 149.214)',
    errorColor: 'oklch(0.577 0.245 27.325)',
    warningColor: 'oklch(0.705 0.213 47.604)',
    infoColor: 'oklch(0.546 0.245 262.881)',
    primaryTextColor: 'oklch(0.141 0.005 285.823)',
    secondaryTextColor: 'oklch(0.21 0.006 285.885)',
    strokeColor: '#ffffff',
    fillColor: '#ffffff',
  },
});

Dark Theme

toast-vanilla does not support dark theme by default however to achieve dark theme you can use your application css variables that supports dark/light theme

/* Light mode */
:root {
  --background: #e4e4e4;
  --foreground: #161616;
  --card: #eeeded;
  --primary: #0e0e0e;
  --primary-foreground: #fceded;
  --secondary: #1a1a1a;
  --border: #8f8f8f;
}
/* Dark mode */
.dark {
  --background: #161616;
  --foreground: #e4e4e4;
  --card: #292727;
  --primary: #fceded;
  --primary-foreground: #fceded;
  --secondary: #c7c7c7;
  --border: #363636;
}

Add css variables into your toast instance styles configuration

import { ToastVanilla as Toast } from 'toast-vanilla';
const toast = new Toast({
  position: 'bottom-left',
  styles: {
    background: 'var(--card)',
    primaryTextColor: 'var(--primary)',
    primaryTextColorForeground: 'var(--primary-foreground)',
    secondaryTextColor: 'var(--secondary)',
    border: 'var(--border)',
    // ... more style options
  },
});

Examples

Simple Notification

toast.success('Changes saved');

Notification with Custom Title

toast.info('New features available', {
  title: 'Update',
  variant: 'filled',
});

Track an API Call

const controller = new AbortController();

await toast.promise(
  () =>
    fetch('/api/users', { signal: controller.signal }).then((r) => r.json()),
  {
    loading: 'Fetching users...',
    success: (users) => `Loaded ${users.length} users`,
    error: (err) =>
      err.name === 'AbortError' ? 'Request cancelled' : `Error: ${err.message}`,
    dismissable: true,
    onDismissCallback: () => {
      if (!controller.signal.aborted) {
        controller.abort();
      }
    },
  },
);

File Upload with Loading State

await toast.promise(
  async () => {
    const formData = new FormData();
    formData.append('file', file);
    const res = await fetch('/upload', { method: 'POST', body: formData });
    return res.json();
  },
  {
    loading: 'Uploading file...',
    success: (result) => `Uploaded: ${result.filename}`,
    error: (err) => `Upload failed: ${err.message}`,
    duration: 4000,
  },
);

React Integration

Use ToastVanilla seamlessly in React applications. Initialize it outside of components to maintain a singleton instance:

import { ToastVanilla } from 'toast-vanilla';
import 'toast-vanilla/dist/index.css';

// Initialize outside component to persist across renders
const toast = new ToastVanilla({
  position: 'top-right',
  maxItemToRender: 3,
});

export default function MyComponent() {
  return <button onClick={() => toast.success('Saved!')}>Save</button>;
}

With shadcn/ui CSS Variables

ToastVanilla integrates beautifully with shadcn/ui design systems. Map the toast styles to your design tokens:

import { ToastVanilla } from 'toast-vanilla';
import 'toast-vanilla/dist/index.css';

const toast = new ToastVanilla({
  position: 'top-left',
  maxItemToRender: 3,
  styles: {
    background: 'var(--background)',
    border: 'var(--border)',
    primaryTextColor: 'var(--foreground)',
    secondaryTextColor: 'var(--muted-foreground)',
    strokeColor: 'var(--accent)',
    strokeColorForeground: 'var(--accent-foreground)',
    successColor: 'var(--success)',
    errorColor: 'var(--destructive)',
    warningColor: 'var(--warning)',
    infoColor: 'var(--info)',
  },
});

export default function App() {
  return (
    <div>
      <button onClick={() => toast.success('Success!')}>Show Toast</button>
    </div>
  );
}

Complete React Example

import { useEffect, useState } from 'react';
import { ToastVanilla, type ToastVariant } from 'toast-vanilla';
import 'toast-vanilla/dist/index.css';

const toast = new ToastVanilla({
  position: 'top-left',
  maxItemToRender: 3,
  styles: {
    background: 'var(--background)',
    primaryTextColor: 'var(--foreground)',
    secondaryTextColor: 'var(--muted-foreground)',
    border: 'var(--border)',
  },
});

export default function App() {
  const [darkMode, setDarkMode] = useState(false);

  const handleSuccessToast = (variant: ToastVariant) => {
    toast.success('Operation successful!', { variant });
  };

  const handlePromiseToast = async () => {
    await toast.promise(() => simulateApiCall(), {
      loading: 'Processing your request...',
      success: (data) => `Completed: ${data.message}`,
      error: (err) => `Failed: ${err.message}`,
      variant: 'filled',
    });
  };

  const simulateApiCall = () =>
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ message: 'All done!' });
      }, 3000);
    });

  useEffect(() => {
    if (darkMode) {
      document.documentElement.classList.add('dark');
    } else {
      document.documentElement.classList.remove('dark');
    }
  }, [darkMode]);

  return (
    <div>
      <button onClick={() => setDarkMode(!darkMode)}>
        {darkMode ? 'Light' : 'Dark'} Mode
      </button>

      <section>
        <h2>Default Variant</h2>
        <button onClick={() => handleSuccessToast('default')}>
          Show Success
        </button>

        <h2>Filled Variant</h2>
        <button onClick={() => handleSuccessToast('filled')}>
          Show Filled
        </button>

        <h2>Promise</h2>
        <button onClick={handlePromiseToast}>Start Async Operation</button>
      </section>
    </div>
  );
}

Browser Support

Works in all modern browsers that support ES2020 and CSS variables.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.