ToastContainer
The Vue component that renders toasts. Place it once in App.vue (or in your Nuxt layout). Uses <Teleport to="body"> internally.
<ToastContainer
position="bottom-right"
:max-visible="5"
:gap="8"
:offset-x="16"
:offset-y="16"
:z-index="9999"
theme="system"
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
position | ToastPosition | 'bottom-right' | Default container position (per-toast position option overrides this) |
maxVisible | number | 5 | Maximum number of toasts shown at once; extras wait in a pending queue |
gap | number | 8 | Vertical gap between toasts in pixels |
offsetX | number | 16 | Horizontal distance from the screen edge in pixels |
offsetY | number | 16 | Vertical distance from the screen edge in pixels |
zIndex | number | 9999 | CSS z-index of the container |
expand | boolean | false | Expand all groups immediately (skip collapsed state) |
teleportTo | string | 'body' | CSS selector passed to <Teleport> |
context | ToastContext | global | Pass an isolated context from createToastContext() |
theme | 'light' | 'dark' | 'system' | ToastDesignTokens | — | Theme name or inline token overrides |
stackMode | boolean | false | Sonner-style stack: inactive toasts collapse behind the front one; hover expands |
Multiple containers
A single <ToastContainer> handles all positions automatically — each toast is rendered at its own position option, falling back to the container's position prop:
toast.success('Saved', { position: 'top-right' })
toast.error('Failed', { position: 'bottom-center' })
// Both appear in their respective corners from one <ToastContainer>For fully isolated queues (separate notification zones), use createToastContext() with a dedicated container:
<template>
<!-- Default global queue — bottom right -->
<ToastContainer position="bottom-right" />
<!-- Critical alerts — top center, separate queue -->
<ToastContainer position="top-center" :context="alertCtx" :z-index="10000" />
</template>
<script setup lang="ts">
import { createToastContext, useToast } from 'vue-toast-kit'
const alertCtx = createToastContext()
const alertToast = useToast(alertCtx)
</script>Slots
Override any part of the toast without losing the queue logic:
<ToastContainer>
<!-- Replace the entire toast -->
<template #toast="{ toast, dismiss }">
<MyCustomToast :data="toast" @close="dismiss(toast.id)" />
</template>
</ToastContainer>| Slot | Props | Description |
|---|---|---|
#toast | { toast, dismiss } | Full replacement of one toast (skips all sub-slots) |
#toast-icon | { toast } | Replace the icon only; falls back to ToastIcon |
#toast-content | { toast } | Replace the entire message + actions area |
#toast-action | { toast } | Replace the action / undo buttons; falls back to ToastActions |
#toast-close | { toast, dismiss } | Replace the close button |
#toast-undo | { toast, remaining } | Replace the progress bar at the bottom of the toast |
Grouping
Toasts with the same groupKey are collapsed into a single toast with a +N counter. Clicking the counter toggles the expanded state.
// All three calls produce one visible toast with "+2"
toast.info('New message from Alice', { groupKey: 'messages' })
toast.info('New message from Bob', { groupKey: 'messages' })
toast.info('New message from Carol', { groupKey: 'messages' })The leader toast (first in the group) stays visible; subsequent toasts are hidden but tracked. When the leader is dismissed, the next toast becomes the leader automatically.
Grouping options
| Option | Behaviour |
|---|---|
groupKey: 'my-key' | Enable grouping for this toast |
No groupKey | Toast is always shown individually |
Stack mode (Sonner-style)
Enable stackMode on <ToastContainer> to collapse multiple toasts into a visual stack. The front toast is fully visible; behind it you see up to 2 ghost cards, slightly scaled and offset. Hovering the container expands them back to the normal stacked list.
<ToastContainer :stack-mode="true" position="bottom-right" />Hover to expand, mouse-leave to collapse back.