ztoast logo

Toasts you can put anywhere.

Zero-dependency React notifications.

toast.success("Project saved", <FiCheck />, { bgColor: "#052e16", width: 360 });
Documentation • v0.1.9
One component to mount
Then call it from anywhere
Put a toast anywhere on screen
Smooth motion by default
Countdown bar, pauses on hover
No CSS file to import
Zero runtime dependencies
Works outside React too
Next.js SSR safe
1
Install package
Zero runtime dependencies
npm i ztoast
2
Mount the Toaster
Once, at your root layout
<Toaster />
3
Start toasting
From any file in your codebase
toast.success("Hello World")
That is the entire setup. No provider, no context, no stylesheet to import. Icons, styling, position and motion are all optional and go in the same call.
Upgrading from 0.1.7?

Examples

example.tsx
jsx
toast.success("Successfully toasted!");

Positioning

A position can be a named spot, a distance from the edges, or a coordinate. Toasts that resolve to the same spot share a stack; different spots stack independently. Nothing is clamped to the viewport, so a coordinate can hang a toast off the edge on purpose.

position.tsx
tsx
// 1. one of the nine named spots, each inset 16px from the edges it touches
toast.show("Over here", { position: "top-center" });

// or set the default for every toast
<Toaster position="top-center" />

Playground

Every control below is a real option. Only what you change from the defaults ends up in the generated call, so you can copy it straight into your code.

playground.tsx
tsx
toast.success("Project saved", "💾");
Reading the call

The icon argument is "💾", which replaces the built-in variant icon. Drop the second argument completely and you get the variant icon back.

API reference

Every method, every config option and every default. Numbers mean pixels everywhere, and colours accept hex, rgb(), hsl(), oklch(), rgb(0 0 0 / 50%) and css variables.

toast.show(message, icon?, config?)core
returns: string | number

The neutral variant, with no built-in icon. Every creator has this same signature: only the message is required, and the second argument can be either the icon or the config.

tsx
import { toast } from "ztoast";

toast.show("Your changes have been saved.");
toast.show("Saved", "💾");
toast.show("Saved", { width: 360 });
toast.show("Saved", "💾", { width: 360 });
toast.success(message, icon?, config?)variant
returns: string | number

A success toast with the green check icon, replaced by anything you pass as the icon argument.

tsx
toast.success("Profile updated successfully");

toast.success("Profile updated", "🎉", { duration: 3500 });
toast.error(message, icon?, config?)variant
returns: string | number

Rendered as role="alert" with aria-live="assertive", so screen readers announce it immediately.

tsx
toast.error("Could not connect to database", {
  description: "Check your network settings and try again.",
});
toast.info(message, icon?, config?)variant
returns: string | number

An informational toast.

tsx
toast.info("A new version is available");
toast.warning(message, icon?, config?)variant
returns: string | number

A warning toast.

tsx
toast.warning("Approaching your storage limit");
toast.warn(message, icon?, config?)alias
returns: string | number

An alias of toast.warning. Identical behaviour, shorter to type.

tsx
toast.warn("Login failed");
toast.loading(message, icon?, config?)variant
returns: string | number

Defaults to duration: Infinity, so it stays until you dismiss it or replace it by reusing its id. Pass a duration to override that.

tsx
const id = toast.loading("Deploying application...");

// later
toast.dismiss(id);
toast.promise(promise, messages, config?)async
returns: Promise<T>

Tracks a promise through loading, resolved and rejected in a single toast. It returns the original promise, so you can still await it. success and error accept a node or a function of the resolved value / error.

tsx
const data = await toast.promise(uploadFile(file), {
  loading: "Uploading file...",
  success: (data) => `Uploaded ${data.filename}`,
  error: (err) => `Failed: ${(err as Error).message}`,
});
toast.dismiss(id?)control
returns: void

Plays the exit animation, then removes the toast. Called with no argument it dismisses every toast.

tsx
toast.dismiss(myToastId);

// everything
toast.dismiss();
toast.dismissAll()control
returns: void

The same as calling toast.dismiss() with no argument.

tsx
toast.dismissAll();
useToast()hook
returns: { toasts, ...methods }

Optional hook for components that want to read the live toast list. It returns the imperative api alongside it, works anywhere in the tree, and never throws — there is no provider to be inside of.

tsx
import { useToast } from "ztoast";

function Counter() {
  const { toasts, success } = useToast();

  return (
    <button onClick={() => success("One more")}>
      {toasts.length} on screen
    </button>
  );
}

Upgrading from 0.1.7

0.1.8 replaced the provider and the raw css option names, and later releases keep that same api. Most apps are a two-line change: swap the provider for <Toaster />, then rename the handful of options below.

BEFORE
0.1.7
tsx
import { ToastProvider, ToastViewport } from "ztoast";

<ToastProvider defaultPosition="top-right" defaultDuration={4000}>
  {children}
  <ToastViewport />
</ToastProvider>

toast.show("Saved", {
  icon: <FiCheck />,
  background: "#052e16",
  borderRadius: 18,
  progressBar: true,
});
AFTER
0.1.8+
tsx
import { Toaster } from "ztoast";

<Toaster />
{children}

toast.show("Saved", <FiCheck />, {
  bgColor: "#052e16",
  radius: 18,
});
0.1.70.1.8 and later
<ToastProvider>…<ToastViewport /></ToastProvider><Toaster />
defaultPosition / defaultDuration / defaultProgressBarposition / duration / progress
toast.show(msg, { icon: <I /> })toast.show(msg, <I />) — the object form still works
background / borderRadius / boxShadow / progressBarbgColor / radius / shadow / progress
backgroundGradient / backgroundImagebgColor — it takes gradients and urls
{ position: "top-center", top: "50vh" }{ position: "top-50vh" }
{ offset: { bottom: 40, right: 32 } }{ position: "bottom-40px right-32px" }
progressBar was off by defaultprogress is on by default
useToast() threw outside a provideruseToast() works anywhere and never throws
toasts fired before mount were droppedthey are queued and appear when the Toaster mounts

Gone for good

These exports and options no longer exist. If your editor still autocompletes them, delete your build cache and reinstall.

ToastProviderToastViewportToastContextValueToastProviderPropsToastOptionsToastStyleOptionsToastOffsetOptionsPromiseToastMessagesoffsettop / bottom / left / righttransformborderColorborderWidth