@aspect-ui-01/toast

Lightweight framework-agnostic toast notifications (~2KB)
3,926
Install
npm install @aspect-ui-01/toast
Latest Version:0.6.0
Last Updated:Dec 30, 2025
Links: npm
Maintainer: techbiz

@aspect-ui-01/toast

Lightweight, framework-agnostic toast notifications built with Web Components.

npm version bundle size license


Highlights

  • ðŸŠķ ~2.5 KB gzipped — zero dependencies
  • 🌐 Universal — Angular, React, Vue, Svelte, Astro, vanilla JS
  • ðŸ“ą Responsive — different options for mobile/desktop
  • â™ŋ Accessible — ARIA compliant, respects prefers-reduced-motion
  • ðŸŽĻ Themeable — CSS custom properties
  • 🔒 Encapsulated — Shadow DOM, no style leaks
  • ⚡ Lazy loading — optional deferred loading (~1 KB initial)

Installation

# pnpm
pnpm add @aspect-ui-01/toast

# npm
npm install @aspect-ui-01/toast

# yarn
yarn add @aspect-ui-01/toast

Quick Start

1. Add the component to your HTML

<ui-toast></ui-toast>

2. Import and use

import { toast } from '@aspect-ui-01/toast';

toast.success('Item added to cart');
toast.error('Payment failed');
toast.warning('Low stock');
toast.info('Processing...');

API Reference

Methods

Method Description Returns
toast.success(message, options?) Show success toast string (toast id)
toast.error(message, options?) Show error toast string (toast id)
toast.warning(message, options?) Show warning toast string (toast id)
toast.info(message, options?) Show info toast string (toast id)
toast.remove(id) Remove specific toast void
toast.clear() Remove all toasts void

Options

interface ToastOptions {
  duration?: number;         // Auto-dismiss delay in ms (0 = persistent)
  position?: ToastPosition;  // Toast placement
  animation?: ToastAnimation;// Entry animation
  showCloseButton?: boolean; // Show close button (default: true)
  width?: string;            // Toast width (default: '20rem')
  
  // Responsive overrides
  mobile?: DeviceOptions;
  desktop?: DeviceOptions;
}

interface DeviceOptions {
  position?: ToastPosition;
  animation?: ToastAnimation;
  width?: string;
  duration?: number;
  showCloseButton?: boolean;
}

Positions

type ToastPosition = 
  | 'top-right'     // Default (desktop)
  | 'top-left'
  | 'top-center'    // Default (mobile)
  | 'bottom-right'
  | 'bottom-left'
  | 'bottom-center';

Animations

type ToastAnimation = 
  | 'fade'
  | 'slide-left'
  | 'slide-right'
  | 'zoom';

Default Durations

Type Duration
success 3000ms
error 6000ms
warning 5000ms
info 4000ms

Usage Examples

Basic

import { toast } from '@aspect-ui-01/toast';

// Simple
toast.success('Saved!');

// With duration
toast.info('Processing...', { duration: 5000 });

// Persistent (no auto-dismiss)
toast.error('Connection lost', { duration: 0 });

// Custom position
toast.warning('Low stock', { position: 'bottom-center' });

// Custom animation
toast.success('Done!', { animation: 'zoom' });

Responsive Options

// Different settings for mobile/desktop
toast.success('Order placed', {
  mobile: { 
    position: 'top-center', 
    width: '100%' 
  },
  desktop: { 
    position: 'top-right', 
    width: '22rem' 
  },
});

// Base options with device overrides
toast.info('Syncing...', {
  duration: 5000,
  mobile: { position: 'bottom-center' },
  desktop: { position: 'top-right' },
});

Programmatic Control

// Store toast id
const id = toast.info('Uploading...', { duration: 0 });

// Later, remove it
toast.remove(id);

// Or clear all
toast.clear();

Framework Integration

Angular

// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import '@aspect-ui-01/toast';

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}
<!-- app.component.html -->
<ui-toast></ui-toast>
// any.component.ts
import { toast } from '@aspect-ui-01/toast';

export class MyComponent {
  notify() {
    toast.success('Hello from Angular!');
  }
}

React

import '@aspect-ui-01/toast';
import { toast } from '@aspect-ui-01/toast';

// TypeScript: add to global.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    'ui-toast': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;
  }
}

function App() {
  return (
    <>
      <ui-toast />
      <button onClick={() => toast.success('Hello from React!')}>
        Show Toast
      </button>
    </>
  );
}

Vue

<template>
  <ui-toast />
  <button @click="notify">Show Toast</button>
</template>

<script setup>
import '@aspect-ui-01/toast';
import { toast } from '@aspect-ui-01/toast';

const notify = () => toast.success('Hello from Vue!');
</script>

Svelte

<script>
  import '@aspect-ui-01/toast';
  import { toast } from '@aspect-ui-01/toast';
</script>

<ui-toast />
<button on:click={() => toast.success('Hello from Svelte!')}>
  Show Toast
</button>

Astro

---
// Layout.astro
---
<html>
  <body>
    <slot />
    <ui-toast></ui-toast>
  </body>
</html>

<script>
  import '@aspect-ui-01/toast';
</script>
---
// Page.astro
---
<button id="toast-btn">Show Toast</button>

<script>
  import { toast } from '@aspect-ui-01/toast';
  
  document.getElementById('toast-btn')?.addEventListener('click', () => {
    toast.success('Hello from Astro!');
  });
</script>

Vanilla JS / CDN

<script type="module">
  import { toast } from 'https://unpkg.com/@aspect-ui-01/toast';
  
  document.querySelector('#btn').onclick = () => {
    toast.success('Hello from vanilla JS!');
  };
</script>

<ui-toast></ui-toast>
<button id="btn">Show Toast</button>

Lazy Loading

For performance-critical applications, use lazy loading to defer component registration:

import { toast, registerToast } from '@aspect-ui-01/toast/lazy';

// Register when needed (once)
registerToast();

// Then use normally
toast.success('Hello!');

Bundle Size Comparison

Import Initial Load
Default ~2.5 KB
Lazy ~1 KB (component deferred)

Theming

Customize appearance with CSS custom properties:

ui-toast {
  /* Colors */
  --toast-success: #16a34a;
  --toast-error: #dc2626;
  --toast-warning: #d97706;
  --toast-info: #2563eb;
  
  /* Layout */
  --toast-radius: 8px;
  --toast-shadow: 0 8px 24px rgb(0 0 0 / 15%);
  --toast-max-width: 25rem;
  --toast-z-index: 999999;
  
  /* Typography */
  --toast-font-size: 0.9rem;
  --toast-line-height: 1.35rem;
  --toast-letter-spacing: 0;
}

Responsive Theming

ui-toast {
  --toast-font-size: 0.875rem;
}

@media (min-width: 768px) {
  ui-toast {
    --toast-font-size: 0.9rem;
    --toast-max-width: 28rem;
  }
}

Dark Mode

@media (prefers-color-scheme: dark) {
  ui-toast {
    --toast-success: #22c55e;
    --toast-error: #f87171;
    --toast-warning: #fbbf24;
    --toast-info: #60a5fa;
    --toast-shadow: 0 8px 24px rgb(0 0 0 / 40%);
  }
}

Accessibility

  • Uses role="alert" for screen readers
  • aria-live="polite" for non-intrusive announcements
  • Respects prefers-reduced-motion — animations disabled
  • Keyboard accessible close button with visible focus state
  • Color contrast meets WCAG AA standards

Browser Support

Browser Version
Chrome 67+
Firefox 63+
Safari 13.1+
Edge 79+

No polyfills required for modern browsers.


TypeScript

Full TypeScript support with exported types:

import { toast } from '@aspect-ui-01/toast';
import type { 
  ToastOptions, 
  ToastPosition, 
  ToastAnimation 
} from '@aspect-ui-01/toast';

const options: ToastOptions = {
  duration: 5000,
  position: 'top-center',
  animation: 'zoom',
};

toast.success('Typed!', options);

SSR Compatibility

Works with SSR frameworks (Astro, Next.js, Nuxt, SvelteKit). The component includes SSR guards and only registers in browser environments.


Contributing

Contributions welcome!

# Clone
git clone https://github.com/aspect-ui-1/toast.git
cd toast

# Install
pnpm install

# Dev
pnpm dev

# Test
pnpm test

# Build
pnpm build

License

MIT ÂĐ Aspect UI

Related Packages

hcx

HTML Compiler - Routeless, targetless, remote, runnable routes and more ...

468
@symbiote-native/notifications

expo-notifications wrapped for SymbioteNative — one framework-agnostic core, bui...

848 72
@mecorelabs/free-pdf-sdk

Free PDF SDK: an embeddable, white-label PDF viewer, annotator and editor for th...

207 0

Version History

Version Released License
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2