Toast

Toast displays brief, temporary notifications that provide feedback without interrupting the user's workflow. It supports automatic closing, manual closing, stacking, progress bars, ESC key closing, responsive viewport adaptation, and show/hide animations.

BrToast uses BrConfigProvider for global theme configuration (colors, radius, shadows, z-index, etc.), and supports both component-based and function-based invocation.

Component Features

  • ⏱️ Auto Close: Supports both auto-close and manual close modes.
  • 📚 Stacking: Supports multiple Toasts displaying simultaneously.
  • 📊 Progress Bar: Optional close progress bar showing remaining time.
  • ⌨️ Keyboard Close: Supports ESC key to close.
  • 📐 8 Positions: Supports top/top-left/top-center/top-right/bottom/bottom-left/bottom-center/bottom-right.
  • 🎨 Multiple Variants: Supports Default, Primary, Success, Error, Warning, Info visual styles.
  • 🎨 Theme Configuration: Based on BrConfigProvider for global theming (colors, radius, shadows, z-index tokens).

Basic Usage

Click the button to show a default Toast (auto-close + manual close).

<script setup>
import { BrButton, BrToastProvider, useToast } from '@breezeui/vue'

const { toast } = useToast()

function notify() {
  toast({
    group: 'basic',
    title: 'Saved',
    description: 'Your changes have been saved successfully.',
    showProgress: true,
  })
}
</script>

<template>
  <div class="flex items-center gap-3">
    <BrToastProvider group="basic" />
    <BrButton @click="notify">Show Toast</BrButton>
  </div>
</template>

Variants

Use the variant prop to control the visual style of the Toast:

  • Default: Default style
  • Primary: Primary style
  • Success: Success style
  • Error: Error style
  • Warning: Warning style
  • Info: Info style
<script setup>
import { BrButton, BrToastProvider, useToast } from '@breezeui/vue'

const { toast } = useToast()
</script>

<template>
  <div class="flex flex-wrap items-center gap-3">
    <BrToastProvider group="variants" />

    <BrButton @click="toast({ group: 'variants', title: 'Default', description: 'default variant' })">Default</BrButton>
    <BrButton color="primary" @click="toast({ group: 'variants', title: 'Primary', description: 'primary variant', variant: 'primary' })">Primary</BrButton>
    <BrButton color="success" @click="toast({ group: 'variants', title: 'Success', description: 'success variant', variant: 'success' })">Success</BrButton>
    <BrButton color="danger" @click="toast({ group: 'variants', title: 'Error', description: 'error variant', variant: 'error' })">Error</BrButton>
    <BrButton color="warning" @click="toast({ group: 'variants', title: 'Warning', description: 'warning variant', variant: 'warning' })">Warning</BrButton>
    <BrButton color="info" @click="toast({ group: 'variants', title: 'Info', description: 'info variant', variant: 'info' })">Info</BrButton>
  </div>
</template>

Positioning & Stacking

Supports 8 positions (top/top-left/top-center/top-right/bottom/bottom-left/bottom-center/bottom-right), along with stacking and progress bars.

<script setup>
import { ref } from 'vue'
import { BrButton, BrToastProvider, useToast } from '@breezeui/vue'

const { toast, dismiss } = useToast()

const position = ref('top-left')
const duration = ref(2800)

const positionOptions = [
  { label: 'top', value: 'top' },
  { label: 'top-left', value: 'top-left' },
  { label: 'top-center', value: 'top-center' },
  { label: 'top-right', value: 'top-right' },
  { label: 'bottom', value: 'bottom' },
  { label: 'bottom-left', value: 'bottom-left' },
  { label: 'bottom-center', value: 'bottom-center' },
  { label: 'bottom-right', value: 'bottom-right' },
]

function notify() {
  toast({
    group: 'positions',
    title: 'Custom Position',
    description: `position=${position.value} duration=${duration.value}ms`,
    position: position.value,
    duration: duration.value,
  })
}

function spam() {
  for (let i = 1; i <= 4; i += 1) {
    toast({
      group: 'positions',
      title: `Toast ${i}`,
      description: 'Stacked display',
      position: position.value,
      duration: duration.value + i * 250,
      variant: i % 2 === 0 ? 'primary' : 'default',
    })
  }
}
</script>

<template>
  <div class="space-y-6">
    <BrToastProvider group="positions" :position="position" />

    <!-- Position Selection -->
    <div class="space-y-3">
      <div class="text-sm font-medium text-muted-foreground">Select Position</div>
      <div class="flex flex-wrap gap-2">
        <BrButton
          v-for="opt in positionOptions"
          :key="opt.value"
          :variant="position === opt.value ? 'solid' : 'outline'"
          :color="position === opt.value ? 'primary' : 'default'"
          size="sm"
          @click="position = opt.value"
        >
          {{ opt.label }}
        </BrButton>
      </div>
    </div>

    <!-- Controls -->
    <div class="flex flex-wrap items-end gap-4">
      <div class="space-y-1.5">
        <label class="text-sm font-medium text-muted-foreground">Duration (ms)</label>
        <input
          v-model.number="duration"
          type="number"
          min="500"
          step="100"
          class="flex h-9 w-32 rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
        />
      </div>

      <div class="flex flex-wrap gap-2">
        <BrButton @click="notify">Show Toast</BrButton>
        <BrButton variant="outline" @click="spam">Stack Toasts</BrButton>
        <BrButton variant="outline" @click="dismiss()">Dismiss All</BrButton>
      </div>
    </div>
  </div>
</template>

Theming

Use BrConfigProvider to globally configure default position, radius, shadow, variant colors, and z-index. You can also use utility classes for local overrides.

Global Customization (BrConfigProvider)

<script setup>
import { computed } from 'vue'
import { BrButton, BrConfigProvider, BrToastProvider, useToast } from '@breezeui/vue'

const { toast } = useToast()

const theme = computed(() => ({
  radius: 0.75,
  shadow: '0 20px 25px -5px rgb(0 0 0 / 0.15), 0 8px 10px -6px rgb(0 0 0 / 0.15)',
  zToast: 80,
  primary: '#6366f1',
  success: '#22c55e',
  destructive: '#ef4444',
  warning: '#f59e0b',
  info: '#3b82f6',
}))

const toastConfig = computed(() => ({
  position: 'top-right',
  duration: 3800,
  max: 4,
  closeDelay: 220,
}))
</script>

<template>
  <BrConfigProvider :theme="theme" :toast="toastConfig">
    <div class="space-y-4">
      <BrToastProvider group="theme" />

      <div class="flex items-center justify-between gap-4 rounded-lg border bg-card p-4">
        <div class="space-y-1">
          <div class="text-sm font-medium">Theme Preview</div>
          <div class="text-sm text-muted-foreground">Configure Toast tokens and default behavior globally via BrConfigProvider</div>
        </div>
      </div>

      <div class="flex flex-wrap gap-3">
        <BrButton @click="toast({ group: 'theme', title: 'Primary', description: 'Global configuration', variant: 'primary' })">Primary</BrButton>
        <BrButton variant="outline" @click="toast({ group: 'theme', title: 'Success', description: 'success variant', variant: 'success' })">Success</BrButton>
        <BrButton variant="outline" @click="toast({ group: 'theme', title: 'Error', description: 'error variant', variant: 'error' })">Error</BrButton>
      </div>
    </div>
  </BrConfigProvider>
</template>

Local Override (TailwindCSS Classes)

<script setup>
import { BrButton, BrToastProvider, useToast } from '@breezeui/vue'

const { toast } = useToast()

function customStyle() {
  toast({
    group: 'local',
    title: 'Local Override Style',
    description: "Only via class override current Toast's appearance",
    class: 'rounded-sm shadow-none border-border/60 bg-card text-card-foreground',
    showProgress: true,
  })
}
</script>

<template>
  <div class="flex items-center gap-3">
    <BrToastProvider group="local" />
    <BrButton variant="outline" @click="customStyle">Local override style</BrButton>
  </div>
</template>

API

BrToast

PropTypeDefaultDescription
openbooleanundefinedControlled open state (use with @update:open/v-model:open).
defaultOpenbooleanfalseUncontrolled initial open state.
durationnumberundefinedAuto-close duration (ms) for this toast. Overrides Provider's duration.
variant'default' | 'primary' | 'success' | 'error' | 'warning' | 'info''default'Visual variant style.
positionBrToastPositionundefinedPosition for this toast. Overrides Provider/BrConfigProvider.
dismissiblebooleantrueWhether to show close button and allow manual closing.
showProgressbooleanfalseWhether to show auto-close progress bar (requires duration > 0).
titlestring | ComponentundefinedTitle content (or use #title slot).
descriptionstring | ComponentundefinedDescription content (or use #description slot).
iconComponentundefinedIcon content (or use #icon slot).
classstring''Additional TailwindCSS classes for local style overrides.

BrToastProvider

PropTypeDefaultDescription
positionBrToastPositionundefinedOverrides BrConfigProvider's default position.
durationnumberundefinedOverrides BrConfigProvider's default auto-close duration (ms).
closeDelaynumberundefinedDelay (ms) before removing from stack after closing, to preserve exit animation.
maxnumberundefinedMaximum number of stacked toasts. Older toasts are removed when exceeded.
closeOnEscapebooleanundefinedWhether to allow closing the latest toast with ESC key.
viewportClassstring''Additional classes for the Viewport, for local layout overrides.

useToast

FieldTypeDefaultDescription
toast(options: BrToastOptions) => { id, dismiss, update }-Triggers a toast and returns a handle (can update/dismiss).
dismiss(id?: string) => void-Dismisses a specific toast. If id is omitted, dismisses all.
update(id: string, patch: BrToastOptions) => void-Updates a specific toast's configuration (title/description/variant/duration etc.).
toastsRef<BrToastItem[]>-Current list of toasts (for custom rendering scenarios).