Skip to content

Toast

Queue concise feedback and announce it without interrupting the current task.

Usage

Auto dismiss

Dismiss transient feedback automatically after a short delay while keeping a visible close action.

Dismiss transient feedback automatically after a short delay while keeping a visible close action.

Persistent

Keep feedback visible until the user explicitly dismisses it.

Keep feedback visible until the user explicitly dismisses it.

Limited

Enforce the configured item or visible-notification limit without losing existing values.

Enforce the configured item or visible-notification limit without losing existing values.

Calling from setup

Call useToast() in the setup of a component below ToastProvider. Its returned state and functions can be used from templates, event handlers, or asynchronous functions. The component that declares the provider is above that provider and cannot read its context from the same setup. Place callers inside the provider slot.

template
<!-- AppShell.vue -->
<ToastProvider v-slot="{ toasts }">
  <RequestButton />
  <ToastViewport class="toast-viewport">
    <ToastRoot v-for="item in toasts" :key="item.id" :value="item.id" class="toast-item">
      <ToastTitle />
      <ToastDescription />
      <ToastClose>Dismiss</ToastClose>
    </ToastRoot>
  </ToastViewport>
</ToastProvider>
ts
// RequestButton.vue <script setup>
const { toast, update } = useToast()

async function save() {
  const id = crypto.randomUUID()
  toast({ id, title: 'Saving', kind: 'deployment-pending', durationMs: null })
  try {
    const result = await saveRelease()
    update(id, { title: 'Saved', kind: 'deployment-complete', durationMs: 3_000 })
    return result
  } catch (error) {
    update(id, { title: 'Save failed', description: 'Try again.', kind: 'error', durationMs: 5_000 })
    throw error
  }
}

Sectile does not execute request functions or consume their errors. The application chooses pending, success, and failure copy, timing, and error disclosure. The application that composes the provider's compound parts also owns markup, icons, classes, placement, and motion.

kind is a user-defined string, not a predefined enum. An omitted or blank value defaults to info; every other value is preserved through data-kind. For backward-compatible accessibility semantics, exactly error uses role="alert" and every other kind uses role="status".

Styling directly with CSS

When no icon or extra configuration is needed, use data-kind selectors without a registry.

css
.toast-item[data-kind='deployment-pending'] {
  background: var(--toast-pending-background);
}

.toast-item[data-kind='deployment-complete'] {
  background: var(--toast-complete-background);
}

Registering classes and icons

Register kind presentation in a normal application object rather than a Sectile global registry. Handle unregistered values with an explicit fallback.

ts
// toast-kinds.ts
import type { Component } from 'vue'
import InfoIcon from './InfoIcon.vue'
import SpinnerIcon from './SpinnerIcon.vue'
import SuccessIcon from './SuccessIcon.vue'
import ErrorIcon from './ErrorIcon.vue'

interface ToastKindPresentation {
  readonly class: string
  readonly icon: Component
}

export const toastKinds = {
  info: { class: 'toast--info', icon: InfoIcon },
  'deployment-pending': { class: 'toast--pending', icon: SpinnerIcon },
  'deployment-complete': { class: 'toast--complete', icon: SuccessIcon },
  error: { class: 'toast--error', icon: ErrorIcon },
} as const satisfies Record<string, ToastKindPresentation>

export type AppToastKind = keyof typeof toastKinds

const fallbackKind: ToastKindPresentation = {
  class: 'toast--unknown',
  icon: InfoIcon,
}

export function resolveToastKind(kind: string): ToastKindPresentation {
  return kind in toastKinds
    ? toastKinds[kind as AppToastKind]
    : fallbackKind
}
template
<ToastRoot
  v-for="item in toasts"
  :key="item.id"
  :value="item.id"
  :class="resolveToastKind(item.kind).class"
>
  <component :is="resolveToastKind(item.kind).icon" />
  <ToastTitle />
  <ToastDescription />
</ToastRoot>

Restricting kinds inside an application

Sectile accepts every string, while an application wrapper can narrow calls to registered kinds.

ts
// use-app-toast.ts
import type { ToastInput } from '@sectile/vue/toast'
import { useToast } from '@sectile/vue/toast'
import type { AppToastKind } from './toast-kinds'

type AppToastInput = Omit<ToastInput<string>, 'kind'> & {
  readonly kind?: AppToastKind
}

export function useAppToast() {
  const api = useToast()
  return {
    ...api,
    toast(input: AppToastInput) {
      api.toast(input)
    },
  }
}

API

Vue package: @sectile/vue/toast

Components
  • ToastProvider
  • ToastPortal
  • ToastViewport
  • ToastRoot
  • ToastTitle
  • ToastDescription
  • ToastClose

Functions

useToast

ts
function useToast(): UseToastReturn

Props

ToastProviderProps

closeLabel

Accessible label announced for each notification close action.

defaultDurationMs

Initial timer duration in milliseconds.

dismissOnEscape

Whether Escape dismisses the focused notification.

hotkey

Document hotkey that moves focus to the notification viewport, or false to disable it.

initialToasts

Notifications present when the provider first mounts.

maxVisible

Maximum number of notifications shown at once.

pauseOnWindowBlur

Whether automatic dismissal pauses while the browser window is inactive.

swipeDirection

Direction in which a pointer swipe dismisses a notification.

swipeThreshold

Pointer travel in pixels required to dismiss by swiping.

toasts

Current notifications when the provider is controlled by the parent.

ToastPartProps

as

Element or component rendered for this part.

asChild

Whether to merge this part into its single child instead of rendering a wrapper.

ToastPortalProps

defer

Whether Teleport target resolution waits until the end of the current mount or update tick.

disabled

Whether interaction is unavailable.

to

Teleport target for portalled content.

ToastRootProps

as

Element or component rendered for this part.

asChild

Whether to merge this part into its single child instead of rendering a wrapper.

value

Current value exposed by this contract.

Slots

ToastProviderSlotProps

dismiss

Dismisses one notification.

dismissAll

Dismisses every notification.

paused

Whether automatic updates are paused.

toast

Notification represented by this item.

toasts

Current notification collection.

update

Updates one notification without replacing its identifier.

ToastRootSlotProps

open

Whether the associated popup or disclosure is open.

toast

Notification represented by this item.

Events

ToastProvider

update:toasts

Emitted when the provider requests a new controlled notification collection.

Other types

UseToastReturn

NameTypeRequired
toastsComputedRef<readonly ToastItem<string>[]>Yes
pausedComputedRef<boolean>Yes
toastvoidYes
updatevoidYes
dismissvoidYes
dismissAllvoidYes

Parts

Shared scope: [data-scope="toast"]. Combine it with a part selector to keep styles local to this component.

PartSelectorRoleExtra attributes
viewport[data-part="viewport"]Clips and positions the currently visible content.
root[data-part="root"]Defines the component boundary and owns its composed parts.
title[data-part="title"]Labels the associated content.
description[data-part="description"]Describes the associated content or decision.
close[data-part="close"]Closes or dismisses the current surface.

Keyboard interaction

KeyBehavior
F8Move focus to the notification viewport.
Tab / Shift+TabMove between notification action controls.
EscapeDismiss the focused notification.
Pointer swipeDismiss a notification after moving it past the configured threshold.

Accessibility

The viewport preserves announcement order and keyboard access; each visible toast has a localized dismiss action and pauses while interaction or window state requires it.

Released under the MIT License.