Install & Download:
# Yarn
$ yarn add vue-toastflow
# NPM
$ npm install vue-toastflow
# PNPM
$ pnpm install vue-toastflowDescription:
Toastflow is a headless toast notification component that manages notification state through a framework-agnostic store and a Vue renderer.
It separates logic from presentation to handle stack animations, timers, and queue management with deterministic rules.
Features
- Framework-Agnostic Store: The core logic operates independently of the UI framework to manage state.
- CSS-First Theming: You can customize appearance by modifying specific CSS variables .
- Headless Rendering: The component exposes a slot to render custom markup while retaining store logic.
- Deterministic Behavior: The engine enforces strict rules for duplicates, timer pauses, and stack eviction.
- Async Promise Handling: It updates toast states automatically based on promise resolution or rejection.
- Interactive Buttons: You can inject action buttons directly into the notification layout.
Preview

Use Cases
- API Status Feedback: Display loading indicators that transition to success or error messages upon request completion.
- Undo Actions: Present a temporary notification with a button to reverse a deletion or state change.
- System-Wide Alerts: Broadcast maintenance warnings or connection errors that persist until dismissed.
- Custom Design Systems: Implement a notification UI that strictly adheres to internal brand guidelines using headless slots.
How to Use It
1. Install the component with a package manager you prefer.
pnpm add vue-toastflow
# or
npm install vue-toastflow2. Initialize the plugin in your main entry file. This step configures global defaults such as position and duration.
// main.ts
import { createApp } from "vue";
import App from "./App.vue";
import { createToastflow, ToastContainer } from "vue-toastflow";
const app = createApp(App);
app.use(
createToastflow({
position: "top-right",
duration: 5000, // Default duration in ms
maxVisible: 5, // Limit the stack size
})
);
// Register the container component globally
app.component("ToastContainer", ToastContainer);
app.mount("#app");3. Place the ToastContainer in your root component. This component renders the active toast stack.
<!-- App.vue -->
<template>
<ToastContainer />
<RouterView />
</template>4. You can then trigger notifications from any file using the toast helper.
import { toast } from "vue-toastflow";
// Simple success message
toast.success({
title: "Profile Updated",
description: "Your changes have been saved."
});
// Error message with an ID for manual control
const errorId = toast.error({
title: "Connection Failed",
description: "Retrying..."
});
// Update the existing toast later
setTimeout(() => {
toast.update(errorId, { description: "Connection restored." });
}, 2000);5. Toastflow tracks promise states automatically. It shows a loading state initially and switches to success or error based on the result.
const saveData = async () => {
const request = fetch("/api/save", { method: "POST" });
await toast.loading(
() => request.then((res) => res.json()),
{
loading: {
title: "Saving...",
description: "Please wait while we process your data."
},
success: (data) => ({
title: "Success",
description: `Record ${data.id} created successfully.`,
}),
error: (err) => ({
title: "Error",
description: err.message || "Something went wrong.",
}),
}
);
};6. You can take full control of the markup by using the scoped slot in ToastContainer. This method lets you use your own CSS classes or utility framework like Tailwind CSS.
<template>
<ToastContainer v-slot="{ toast, dismiss }">
<div
class="custom-toast"
:class="toast.type"
@click="dismiss(toast.id)"
>
<div class="toast-header">
<strong>{{ toast.title }}</strong>
<button @click.stop="dismiss(toast.id)">Close</button>
</div>
<p>{{ toast.description }}</p>
</div>
</ToastContainer>
</template>7. Available configuration options. You can pass these options to createToastflow or individual toast calls.
| Option | Type | Default | Description |
|---|---|---|---|
position | String | "top-right" | Screen position (e.g., top-left, bottom-center). |
duration | Number | 5000 | Time in ms before auto-dismiss. 0 or Infinity disables it. |
maxVisible | Number | 5 | Maximum number of toasts displayed at once. |
order | String | "newest" | Stack order strategy (newest or oldest). |
preventDuplicates | Boolean | false | Prevents rendering identical toasts. |
pauseOnHover | Boolean | true | Pauses the timer when the user hovers over the toast. |
closeOnClick | Boolean | false | Dismisses the toast when clicked. |
supportHtml | Boolean | false | Enables HTML rendering in title and description. |
buttons | Object | undefined | Configuration for action buttons inside the toast. |
8. API Methods:
| Method | Description |
|---|---|
toast.show(options) | Renders a generic toast. |
toast.success(options) | Renders a success variant. |
toast.error(options) | Renders an error variant. |
toast.loading(promise, options) | Wraps a promise with loading/success/error states. |
toast.dismiss(id) | Removes a specific toast by ID. |
toast.dismissAll() | Clears all active toasts. |
toast.update(id, options) | Updates the content or options of an active toast. |
Related Resources
FAQs
Q: Can I use Toastflow with Nuxt?
A: Yes, Toastflow works with Nuxt.
Q: How do I customize the animations?
A: You can override the default CSS classes or provide custom class names in the animation configuration object.
Q: Does it support right-to-left (RTL) layouts?
A: The library does not enforce directionality, so you can handle RTL by applying standard CSS to the container or custom slots.
Q: Can I render HTML content inside the toast?
A: Yes, you can enable the supportHtml option to render HTML strings in the title or description fields.





