Skip to content

Справочник ​

Архитектура ​

useToast() / toast (singleton)
        │
        ├── buildToastApi(context)
        │     toast(), toast.success/error/warning/info/loading/custom()
        │     toast.promise()   — updates type + restarts timer
        │     toast.undo()      — wraps options.undo
        │     toast.dismiss()   — proxies to queue.dismiss()
        │
        ▼
   ToastContext
        │   addToast()  →  isServer ? ToastBuffer : ToastQueue.add()
        │   dismiss()   →  ToastQueue.dismiss()
        │   update()    →  ToastQueue.update()
        │
        ▼
   ToastQueue                    GroupManager
        active: ToastItem[]  ◄───────────────────┐
        pending: ToastItem[]      add(id, key)    │
        timers: Map<id, UndoTimer>  remove(id, key)│
                                  toggleExpand()  │
        add()  — dedup / preempt / sort pending   │
        remove() — free slot, promote from pending│
        update() — merge + restart timer on duration│
        dismiss() — calls onClose, remove         │
                                                  │
   UndoTimer                                      │
        setTimeout/setInterval, pause/resume       │
        remaining: number (0–1)  ────────────────►│ ToastItem.remaining.value
        onExpire: () => queue.remove(id)          │
                                                  │
   ToastBuffer (SSR)                              │
        push() — store before window exists       │
        flush() — replay into queue at mount      │
        onFlush() — called by ToastContainer      │
                                                  │
   ToastContainer.vue                             │
        Teleport → body                           │
        TransitionGroup (slide + fade per position)│
        hover → queue.pauseAll() / resumeAll()    │
        visibilitychange → pause/resume           │
        position/theme/maxVisible default to      │
          inject(GLOBAL_OPTIONS_KEY) when the      │
          matching prop isn't passed explicitly    │
        slot: #toast / #toast-icon / …            │
        │                                         │
        └── Toast.vue                             │
              swipe (touch)                       │
              aria role + aria-live               │
              ToastIcon.vue (SVG + spinner)        │
              ToastProgressBar.vue (scaleX)       │
              action / undo buttons               │
              group counter (click → toggleExpand)│

Plugin (VueToastPlugin)                 Nuxt Module
  app.use() → installContext()            defineNuxtModule()
  provide(TOAST_CONTEXT_KEY, ctx)         addPlugin(resolver.resolve('./plugin'))
  provide(GLOBAL_OPTIONS_KEY, opts)         → own dist/nuxt/plugin.{js,cjs} entry
  app.component('ToastContainer', …)      addImports()/addComponent() source from
                                             the package's main entry (already built)
                                           css inject

Поддержка SSR ​

СценарийПоведение
typeof window === 'undefined'Вызовы toast() буферизуются в ToastBuffer; browser API не затрагивается
<ToastContainer> монтируется на клиентеБуфер сбрасывается через 100 мс со всеми ожидающими тостами
ignoreSSR: trueБуфер отключён; тосты, вызванные на SSR, тихо отбрасываются
Гидратация NuxtПлагин работает и на SSR тоже (это универсальный плагин Nuxt, не только клиентский) — отсутствие HTML тостов на сервере связано с рендером ToastContainer, а не с плагином
ts
// nuxt.config.ts — отключить SSR-буфер, если тосты никогда не вызываются на сервере
vueToastKit: {
  ignoreSSR: true
}

Доступность ​

ВозможностьРеализация
role="alert" / role="status"alert для типа error/warning или приоритета critical; status в остальных случаях
aria-live"assertive" для приоритета critical (либо переопределение options.ariaLive); "polite" в остальных случаях
aria-atomic="true"Всегда установлен на элементе тоста
tabindex="0"Только когда тост закрываемый, имеет действие или кнопку отмены
Клавиша EscapeЗакрывает тост в фокусе (только если закрываемый); фокус возвращается на элемент, активный до появления тоста
Кнопка закрытияaria-label="Close"
Счётчик группыrole="button" + aria-label="Show all (N)"
ToastIcon / ToastProgressBararia-hidden="true" (декоративные)
Обёртка позиции <ToastContainer>role="region" + aria-label="Notifications", только пока в этой позиции есть активные тосты
КлавиатураEscape закрывает тост в фокусе; другого встроенного клавиатурного взаимодействия нет (кнопки закрытия/действия/отмены — обычные фокусируемые кнопки)

Размер бандла и peer-зависимости ​

Точка входаРазмер (gzip)Peer-зависимости
vue-toast-kit (JS)~9.2 KBvue ^3.3
vue-toast-kit/style (CSS)~2.4 KB—
vue-toast-kit/nuxt~0.6 KBvue ^3.3, @nuxt/kit

Поставляется как tree-shakeable ESM (vue-toast-kit.js) и CommonJS (vue-toast-kit.cjs).

Сравнение ​

vue-toastificationvue-sonnervue-toast-kit
useToast()—useToast()
toast(msg, { type: TYPE.SUCCESS })toast.success(msg)toast.success(msg)
toast(msg, { type: TYPE.ERROR })toast.error(msg)toast.error(msg)
toast(msg, { type: TYPE.WARNING })—toast.warning(msg)
toast(msg, { type: TYPE.INFO })toast(msg)toast.info(msg)
toast.loading(msg)toast.loading(msg)toast.loading(msg)
POSITION.BOTTOM_RIGHT—'bottom-right'
POSITION.TOP_CENTER—'top-center'
toast.dismiss(id)toast.dismiss(id)toast.dismiss(id)
toast.update(id, opts)—toast.update(id, opts)
—toast.promise()toast.promise()
——toast.undo()
——Очередь приоритетов
——Группировка
——useToastState() headless
——createToastContext()

Миграция ​

Миграция с vue-toastification ​

ts
// До
import { useToast, TYPE, POSITION } from 'vue-toastification'
const toast = useToast()
toast('Hello', { type: TYPE.SUCCESS, position: POSITION.BOTTOM_RIGHT })

// После
import { useToast } from 'vue-toast-kit'
const toast = useToast()
toast.success('Hello') // позиция задаётся глобально в плагине

Миграция с vue-sonner ​

toast.success(), toast.error(), toast.promise() и toast.dismiss() идентичны. Единственное отличие — <ToastContainer /> заменяет <Toaster />:

vue
<!-- До (vue-sonner) -->
<Toaster position="bottom-right" />

<!-- После (vue-toast-kit) -->
<ToastContainer position="bottom-right" />

Разработка ​

bash
git clone https://github.com/macrulezru/vue-toast-kit.git
cd vue-toast-kit
npm install
npm run build       # vite build + tsc --emitDeclarationOnly
npm run typecheck   # tsc --noEmit
npm run lint        # eslint --fix
npm test            # vitest run

Запуск интерактивного демо — см. Демо.

Лицензия ​

MIT