Toaster
Bake your Toast and let it fly! You should insert in into your <body>
The toaster uses the Popover API (popover="manual") so toasts always appear in the top-layer — even above open dialogs. Use toasterObserver to show/hide the toaster popover automatically as toasts are added and removed.
Installation
Follow instructions for individual framework usage below
Styles
Variants
Props
Scripts
The Toaster script shows or hides the toaster popover as toasts are added or removed.
INFO
For winduum-elements and winduum-stimulus, toasts are expected to be appended into the Toaster from the backend, for example via ajax. You can also append the HTML manually, for example with insertAdjacentHTML.
Examples
Default
The toaster lives at the end of your <body> — toasts are inserted into it and the popover shows/hides automatically via toasterObserver.
<button class="x-button" id="showToast">Append toast</button>
<button class="x-button muted" command="--close" commandfor="toasterDefault">Close all</button>
<template id="toastTemplate">
<x-toast class="x-toast" role="status" aria-live="assertive" aria-atomic="true">
<div class="x-toast-content">
<div class="flex-col">
<div class="x-title">Hello toast</div>
<div class="x-text">Amazing toast</div>
</div>
<button class="x-button muted ml-auto" command="--close">Close</button>
</div>
</x-toast>
</template>
<x-toaster class="x-toaster items-end" popover="manual" id="toasterDefault"></x-toaster><div data-controller="invoke">
<button class="x-button" id="showToast">Append toast</button>
<button class="x-button muted" data-action="click->invoke#action" data-invoke-action="x-toaster#close" data-invoke-target="#toasterDefault">Close all</button>
<template id="toastTemplate">
<li class="x-toast" data-controller="x-toast" data-action="x-toast:connect->x-toast#show" role="status" aria-live="assertive" aria-atomic="true">
<div class="x-toast-content">
<div class="flex-col">
<div class="x-title">Hello toast</div>
<div class="x-text">Amazing toast</div>
</div>
<button class="x-button muted ml-auto" data-action="click->x-toast#close">Close</button>
</div>
</li>
</template>
<ol class="x-toaster items-end" popover="manual" id="toasterDefault" data-controller="x-toaster"></ol>
</div><script setup lang="ts">
import { ref } from 'vue'
import { Button } from '@/components/button'
import { Title } from '@/components/title'
import { Text } from '@/components/text'
import { Toast, ToastContent } from '@/components/toast'
import { Toaster } from '@/components/toaster'
const toasts = ref<number[]>([Date.now()])
const closeToast = (toast: number) => {
toasts.value = toasts.value.filter(item => item !== toast)
}
const closeToaster = () => {
toasts.value = []
}
</script>
<template>
<Button class="muted" @click="closeToaster">Close all</Button>
<Toaster class="items-end">
<Toast v-for="toast in toasts" :key="toast" @close="closeToast(toast)">
<ToastContent>
<div class="flex-col">
<Title>Hello toast</Title>
<Text>Amazing toast</Text>
</div>
<Button class="muted ml-auto" data-action="closeToast">Close</Button>
</ToastContent>
</Toast>
</Toaster>
</template>import { useState } from "react"
import { Button } from "@/components/button"
import { Title } from "@/components/title"
import { Text } from "@/components/text"
import { Toast, ToastContent } from "@/components/toast"
import { Toaster } from "@/components/toaster"
export function Example() {
const [toasts, setToasts] = useState<number[]>([Date.now()])
const closeToast = (toast: number) => {
setToasts(current => current.filter(item => item !== toast))
}
const closeToaster = () => {
setToasts([])
}
return (
<>
<Button className="muted" onClick={closeToaster}>Close all</Button>
<Toaster className="items-end">
{toasts.map((toast) => (
<Toast key={toast} onClose={() => closeToast(toast)}>
<ToastContent>
<div className="flex-col">
<Title>Hello toast</Title>
<Text>Amazing toast</Text>
</div>
<Button className="muted ml-auto" data-action="closeToast">Close</Button>
</ToastContent>
</Toast>
))}
</Toaster>
</>
)
}JavaScript API
closeToaster
- Type:
(element: HTMLElement, options?: CloseToastOptions) => void - Kind:
sync
All toasts are closed at once.
Example
import { closeToaster } from 'winduum/src/components/toaster'
document.querySelector('#closeToaster').addEventListener('click', () => {
closeToaster(document.querySelector('.x-toaster'))
})toasterObserver
- Type:
() => MutationObserver - Kind:
sync
Returns a MutationObserver that shows the toaster popover when the first toast is inserted and hides it when the last toast is removed. Observe the toaster element with { childList: true }.
Example
import { toasterObserver } from 'winduum/src/components/toaster'
const observer = toasterObserver()
observer.observe(document.querySelector('.x-toaster'), {
childList: true,
})