Premium toasts in <5 kB.
Anywhere you write JavaScript.
A zero-dependency, universal toast library. Vanilla, React, Vue, Next.js, PHP, Django — same API, three formats (ESM / CJS / CDN), glassmorphism out of the box.
Tweak it, fire it, copy the snippet.
Every option you toggle here maps 1:1 to a real config key. Drop the generated snippet straight into your app.
toast.success(
"Listing saved!",
{
position: "bottom-right",
duration: 4000, // ms
pauseOnHover: true,
progress: true,
swipeToDismiss: true,
},
);Twelve premium features. Zero compromises.
Everything you'd reach for in a full-fat notification system, packed into a tiny universal bundle.
Tiny, tree-shakeable, single file. No CSS to import.
Built-in backdrop-blur, themeable via CSS variables.
loading → success / error transitions in one call.
Per-position max-visible with FIFO queue overflow.
Pointer events — mouse and touch — out of the box.
Real time tracking, not setTimeout drift.
Independent stacks per corner / edge / center.
Reads prefers-color-scheme and updates live.
role=status / alert, aria-live, focusable close.
Drop in any markup, avatars, actions, descriptions.
Every color, radius, shadow, font — overridable.
ESM / CJS / UMD — works with every framework.
Pick your package manager. Or skip it entirely.
Use npm/pnpm/yarn/bun, or load the UMD bundle straight from a CDN — same exports, same API.
npm install uivibe-pro-toasterThree lines. Done.
No mount step. No provider. No CSS import. The library injects its own styles on the first call and is fully SSR-safe — call it from any client code path.
- ✓ No
<Toaster />mount - ✓ No
import "./styles.css" - ✓ No SSR pre-render mismatch — DOM is only touched in the browser
- ✓ Singleton container survives client-side navigation
import { toast } from "uivibe-pro-toaster";
toast.success("Listing saved!");
toast.error("Something broke", { duration: 6000 });
toast.info("Heads up — new update available");
// Promise pipeline:
toast.promise(api.save(form), {
loading: "Saving…",
success: "Saved!",
error: "Failed to save",
});
No build step required.
Drop a single <script> tag from unpkg or jsDelivr. The global window.Toast is the same callable API you get from npm.
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Toast demo</title>
</head>
<body>
<button id="b">Save</button>
<script src="https://unpkg.com/uivibe-pro-toaster/dist/index.global.js"></script>
<script>
Toast.configure({ position: "top-right", duration: 4000, theme: "auto" });
document.getElementById("b").addEventListener("click", () => {
Toast.success("Listing saved!");
});
</script>
</body>
</html>
First-class React. SSR-safe by design.
In the App Router, call toast from any client component or event handler. No provider needed — the singleton manager handles mount, queue, and unmount for you.
// app/components/SaveButton.tsx
"use client";
import { useEffect } from "react";
import { toast } from "uivibe-pro-toaster";
export default function SaveButton() {
useEffect(() => {
toast.configure({ position: "bottom-right", theme: "auto" });
}, []);
const save = async () => {
await toast.promise(fetch("/api/save").then((r) => r.json()), {
loading: "Saving…",
success: (data) => `Saved #${data.id}`,
error: (err) => `Failed: ${err.message}`,
});
};
return <button onClick={save}>Save listing</button>;
}
Try it inline
This button is a normal React handler firing toast.success.
Works identically in Vite, Remix, Astro's React islands, and Solid (via @solidjs/start).
Composable. Reactive-friendly.
The same singleton works inside setup(), composables, or any client-side script. Configure once on onMounted and you're done.
<!-- App.vue -->
<script setup lang="ts">
import { onMounted } from "vue";
import { toast } from "uivibe-pro-toaster";
onMounted(() => toast.configure({ position: "top-center", theme: "auto" }));
const save = () => toast.success("Listing saved!");
</script>
<template>
<button @click="save">Save</button>
</template>
Loading. Success. Or error. One call.
Hand toast.promise any promise and three messages. It shows a spinner while pending, then swaps to a success / error toast based on the outcome.
import { toast } from "uivibe-pro-toaster";
async function saveListing(form: FormData) {
return toast.promise(
fetch("/api/listings", { method: "POST", body: form }).then((r) => {
if (!r.ok) throw new Error("Bad request");
return r.json();
}),
{
loading: "Saving listing…",
success: (data) => `Saved listing #${data.id}`,
error: (err) => err instanceof Error ? err.message : "Failed",
},
{ duration: 5000 },
);
}
Ten methods. That's the whole API.
Fully typed. Importable as named export { toast } or default.
| Method | Returns | Description |
|---|---|---|
| toast(message, options?) | string | Show a default-type toast. Returns the toast id. |
| toast.success(message, options?) | string | Green success toast with checkmark icon. |
| toast.error(message, options?) | string | Red error toast; uses role="alert", aria-live="assertive". |
| toast.info(message, options?) | string | Blue info toast. |
| toast.warning(message, options?) | string | Amber warning toast. |
| toast.loading(message, options?) | string | Sticky toast with spinner — duration defaults to Infinity. |
| toast.promise(promise, messages, options?) | Promise<T> | Pipes a promise through loading → success/error toasts. |
| toast.update(id, partial) | void | Mutate type, message, description, or duration of a live toast. |
| toast.dismiss(id?) | void | Dismiss one (by id) or all toasts when id is omitted. |
| toast.configure(globalConfig) | void | Set default options applied to every subsequent call. |
Configure once, override per toast.
toast.configure() sets defaults for every subsequent call. Per-toast options always win.
// Set defaults once, anywhere on the client.
import { toast } from "uivibe-pro-toaster";
toast.configure({
position: "bottom-right", // 9 positions
duration: 5000, // ms — Infinity for sticky
maxVisible: 4, // queue overflow per position
gap: 12, // px between stacked toasts
theme: "auto", // 'light' | 'dark' | 'auto'
zIndex: 9999,
pauseOnHover: true,
swipeToDismiss: true,
progress: true,
dismissible: true,
});
| Option | Type | Default | Notes |
|---|---|---|---|
| duration | number | Infinity | 4000 | ms before auto-dismiss. Infinity = sticky. |
| position | Position | "top-right" | One of 9 positions (top/middle/bottom × left/center/right). |
| icon | string | false | auto | Custom SVG/HTML or false to hide. |
| description | string | — | Secondary line under the title. |
| action | { label, onClick } | — | Inline action button (e.g. Undo). |
| html | string | — | Raw custom HTML — bypasses default layout. |
| dismissible | boolean | true | Show / hide the close (×) button. |
| pauseOnHover | boolean | true | Pause timer + progress on hover/focus. |
| swipeToDismiss | boolean | true | Pointer-event drag to dismiss (mouse + touch). |
| progress | boolean | true | Show the bottom countdown bar. |
| theme | "light" | "dark" | "auto" | "auto" | Reads prefers-color-scheme when auto. |
| className / style | string / CSS | — | DOM passthrough for one-off styling. |
| onShow / onDismiss / onClick | (id) => void | — | Lifecycle callbacks. |
Override one CSS variable. Or all fifteen.
Every visual surface is wired to a CSS custom property. Drop them into :root and they cascade everywhere.
/* Override any of these CSS variables anywhere in your app. */
:root {
--uvt-bg: rgba(255, 255, 255, 0.85);
--uvt-text: #0f172a;
--uvt-muted: #475569;
--uvt-border: rgba(15, 23, 42, 0.08);
--uvt-radius: 16px;
--uvt-shadow: 0 12px 40px -10px rgba(15, 23, 42, .25);
--uvt-success: #16a34a;
--uvt-error: #dc2626;
--uvt-info: #2563eb;
--uvt-warning: #d97706;
--uvt-accent: #6366f1;
--uvt-gap: 14px;
--uvt-padding: 14px 16px;
--uvt-z-index: 9999;
--uvt-font: "Inter", system-ui, sans-serif;
}
Live tweak
--uvt-bg--uvt-text--uvt-muted--uvt-border--uvt-shadow--uvt-radius--uvt-padding--uvt-success--uvt-error--uvt-info--uvt-warning--uvt-accent--uvt-gap--uvt-z-index--uvt-fontPick any corner. Or every corner.
Each position has its own stack and queue, so toasts in different corners never fight for the same screen space.
Built for everyone, on every modern browser.
ARIA-complete out of the box. backdrop-filter degrades to a solid background on older engines.
Errors use alert (assertive). All other types use status (polite) so they don't interrupt the user.
The container is a labelled region. Toasts are announced once and grouped by type.
Close buttons are real <button> elements; Tab focuses them, Enter dismisses.
Focusing a toast freezes its timer — useful for screen-reader users reading the content.
prefers-reduced-motion shrinks enter/exit transitions and progress animations to near-instant.
Iconography conveys type as well as color (✓, ✕, ⓘ, △).
Common questions, then go ship.
Still wondering? Open an issue on GitHub — we read every one.
How big is the bundle, really?+
Under 5 kB gzipped for every output (ESM, CJS, and IIFE/browser-global). No CSS file to import - styles are injected on first call.
Do I need a <Toaster /> provider?+
No. The library uses a singleton manager that auto-mounts on the first toast call. Works the same in Vanilla JS, React, Vue, and any other DOM environment.
Is it SSR-safe with Next.js App Router?+
Yes. Every browser API access is guarded by typeof window !== 'undefined'. Call toast() from any client component or event handler.
Can I customize the look?+
Override any of the ~15 CSS variables (--uvt-bg, --uvt-radius, --uvt-accent, ...) anywhere in your stylesheet, or pass className / style per toast.
How does the queue work?+
Each position has its own visible-set and FIFO queue. When maxVisible is reached, new toasts wait. As old toasts dismiss, the queue promotes the next entry.
Does swipe-to-dismiss work on mobile?+
Yes - it uses Pointer Events, which unify mouse and touch input. Drag past 80 px to dismiss; release earlier to snap back.
Can I update a toast after it's shown?+
Yes - toast.update(id, { type, message, duration }) hot-swaps the content. This is exactly how toast.promise transitions loading to success.
Is it tree-shakeable?+
Yes. The package is marked sideEffects: false and ships ESM. Bundlers will only include the methods you actually call.
Ready to ship better feedback?
Install uivibe-pro-toaster and replace your existing toast library in under five minutes.