@rozie-ui/toast-vue

Idiomatic Vue headless, accessible toast / notification host (queue, auto-dismiss, hover-pause, positioning, imperative show/dismiss/clear handle) — one accessible Rozie source compiled to Vue.
1,675 1
Install
npm install @rozie-ui/toast-vue
Latest Version:0.3.1
Vue:3
License:MIT
Last Updated:Oct 15, 2026
Links: GitHub  ·  npm
Maintainer: serpentblade

@rozie-ui/toast-vue

Idiomatic vue Toaster — a headless, accessible toast / notification host (a live-region queue with per-toast auto-dismiss timers, hover-to-pause, six corner positions, and a per-toast close button) compiled from one Rozie source. It is not a global singleton + context system: the host owns the queue + timers as internal state and exposes an imperative show / dismiss / clear handle you drive via ref — "call from anywhere" is your app's wiring concern (stash the ref). Every visual value is a CSS custom property, so it re-skins to any design system. This package is generated; do not edit src/ by hand.

Install

npm i @rozie-ui/toast-vue

Peer dependencies: vue. Install them alongside this package.

Also installed: @rozie/runtime-vue — Rozie's small, tree-shaken runtime helper package (controllable state, keyboard navigation, event modifiers, and safe interpolation). It arrives as a regular dependency, so npm pulls it for you. This build imports nothing from it today, so it shakes out of your bundle entirely. What's in it and what it costs.

Usage

<script setup lang="ts">
import { ref } from 'vue';
import Toaster from '@rozie-ui/toast-vue';

const toaster = ref();          // template ref → the imperative handle
</script>

<template>
  <button @click="toaster.show({ message: 'Saved!', type: 'success' })">Save</button>
  <button @click="toaster.show({ message: 'Something failed', type: 'error' })">Fail</button>
  <button @click="toaster.show({ message: 'Conversation archived', data: { threadId: 't42' }, action: { label: 'Undo', onClick: (ctx) => restore(ctx.data.threadId) } })">Archive</button>

  <!-- Mount the host once (typically near the app root). -->
  <Toaster ref="toaster" position="bottom-right" :duration="4000" />

  <!-- Custom per-toast chrome via the #toast scoped slot:
  <Toaster ref="toaster">
    <template #toast="{ toast, dismiss }">
      <strong>{{ toast.type }}</strong> {{ toast.message }}
      <button @click="dismiss(toast.id)">OK</button>
    </template>
  </Toaster>
  -->
</template>

Theming

Every visual value is a --rozie-toast-* CSS custom property — override any of them at any ancestor scope. Ready-made design-system bridges ship in the package:

import '@rozie-ui/toast-vue/themes/shadcn.css';    // or material.css, bootstrap.css, base.css

Props

Name Type Default Two-way (model) Required
position String "bottom-right"
duration Number 4000
max Number 0
disablePauseOnHover Boolean false
ariaLabel String null
disableSwipe Boolean false
stacked Boolean false
disableAnnounce Boolean false

Events

Event Description
dismissed Fired exactly once per toast, at dismissal initiation (before the exit animation runs). Payload is ONE object { toast, reason } — toast is the full queue entry, reason is 'timeout' (auto-dismiss), 'swipe' (pointer swipe past threshold), 'close' (the built-in close button), 'action' (the default toast's action button), or 'api' (the dismiss(id) verb). clear() removes every toast immediately and does NOT fire dismissed (documented bulk behavior).

Imperative handle

The component has no events — its primary API is an imperative handle (declared once in the Rozie source via $expose). Grab a handle with the native ref mechanism and call the methods directly. None of the verbs overrides an inherited host-element member, so the Lit custom element emits no ROZ137 warning:

Method Description
show Enqueue a toast. Accepts { message, type, duration, id, action, data } (all optional — message defaults to '', type to 'info', duration to the duration prop). Returns the toast id. A non-sticky toast (duration > 0) auto-dismisses; duration: 0 makes it sticky. action: { label, onClick } renders an action button in the default toast (dropped if onClick is not a function — no dead button ships); clicking it calls onClick({ id, data }) and dismisses with reason 'action' (the dismiss ALWAYS runs, even if onClick throws — the error itself is never swallowed). data is an arbitrary payload carried through untouched, available in the #toast slot scope, the dismissed payload, and the action callback.
dismiss Remove a single toast by the id returned from show (routes through the exit lifecycle with reason 'api' — fires dismissed, plays the exit animation, then removes it).
clear Remove every visible toast at once immediately (no exit animation) and clear all pending auto-dismiss timers. Does NOT fire dismissed.
patch Update an existing toast in place. Accepts (id, { message, type, duration, action, data }) — only the keys you pass are merged into the matching entry. Returns true if the id existed, false otherwise (no throw). Including a duration key clears and restarts that toast's auto-dismiss timer (0 makes it sticky; a positive value arms/re-arms it); omitting duration leaves a running timer untouched. action/data merge the same way show() accepts them — handy for adding an "Undo" action once a promise() toast settles.
promise Sugar over show/patch for an async operation: promise(p, { loading, success, error }) immediately shows a { type: 'loading', duration: 0 } toast and returns its id SYNCHRONOUSLY. On resolve it patches the SAME toast to { type: 'success', message: resolve(success, value) } (the auto-dismiss timer starts AT SETTLE); on reject, likewise with error. success/error accept a string or a (value) => string function. Never resurrects a toast dismissed while p was still pending, and never returns a derived promise — your own .then/.catch on p still fire.
<script setup>
import { ref } from 'vue';
const toaster = ref();          // template ref
</script>

<template>
  <Toaster ref="toaster" />
  <button @click="toaster.show({ message: 'Saved', type: 'success' })">Notify</button>
  <button @click="toaster.clear()">Clear all</button>
</template>

Slots

Slot Params
toast toast, dismiss

Related Packages

@incuca/vue3-toaster

Lightweight toast-notification plugin for Vue 3

5,317 5
cincin-vue

🥂 Vue bindings for cincin: headless composables, primitives, ready-to-use skin

1,694 1
@rozie-ui/combobox-vue

Idiomatic Vue headless WAI-ARIA combobox / autocomplete (text input + popup list...

2,591 1
@rozie-ui/date-picker-vue

Idiomatic Vue headless WAI-ARIA single-date calendar (month grid, prev/next nav,...

1,608 1
@rozie-ui/data-table-vue

Idiomatic Vue headless WAI-ARIA data table (sorting, filtering, pagination, sele...

3,040 1

Version History

Version Released Vue License
0.3.1 ^3.4 MIT
0.3.0 ^3.4 MIT
0.2.3 ^3.4 MIT
0.2.2 ^3.4 MIT
0.2.1 ^3.4 MIT