Skip to content
                              Sponsored by

                              MagicToast

                              MagicToast let’s you trigger and display toasts from anywhere.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-demo" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              </script>

                              Overview

                              Anatomy

                              vue
                              <template>
                                <magic-toast-provider id="your-toast-id" />
                              </template>
                              
                              <script>
                              import { defineAsyncComponent } from 'vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const component = defineAsyncComponent(() => import('./YourToast.vue'))
                              const { add } = useMagicToast('your-toast-id')
                              
                              function handleClick() {
                                add({ component })
                              }
                              </script>

                              Installation

                              CLI

                              Add @maas/vue-equipment to your dependencies.

                              sh
                              pnpm install @maas/vue-equipment
                              sh
                              npm install @maas/vue-equipment
                              sh
                              yarn add @maas/vue-equipment
                              sh
                              bun install @maas/vue-equipment

                              Vue

                              If you are using Vue, import and add MagicToastPlugin to your app.

                              js
                              import { createApp } from 'vue'
                              import { MagicToastPlugin } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const app = createApp({})
                              
                              app.use(MagicToastPlugin)

                              Nuxt

                              The toaster is available as a Nuxt module. In your Nuxt config file add @maas/vue-equipment/nuxt to your modules and add MagicToast to the plugins in your configuration.

                              js
                              export default defineNuxtConfig({
                                modules: ['@maas/vue-equipment/nuxt'],
                                vueEquipment: {
                                  plugins: ['MagicToast'],
                                },
                              })

                              Composable

                              In order to interact with the toaster from anywhere within your app, we provide a useMagicToaster composable. Import it directly when needed.

                              js
                              const component = defineAsyncComponent(() => import('./YourToast.vue'))
                              const { add } = useMagicToast('your-toast-id')
                              
                              function handleClick() {
                                add({ component })
                              }

                              TIP

                              If you have installed the toaster as a Nuxt module, the composable will be auto-imported and is automatically available in your Nuxt app.

                              Peer Dependencies

                              If you haven’t installed the required peer dependencies automatically, you’ll need to install the following packages manually.

                              Installation

                              sh
                              pnpm install @nuxt/kit @vueuse/core defu
                              sh
                              npm install @nuxt/kit @vueuse/core defu
                              sh
                              yarn add @nuxt/kit @vueuse/core defu
                              sh
                              bun install @nuxt/kit @vueuse/core defu

                              API Reference

                              MagicToastProvider

                              The MagicToastProvider wraps the toaster and configures it according to the provided options.

                              Props

                              PropTypeRequired
                              id
                              MaybeRef<string>true
                              options
                              MagicToastOptionsfalse

                              Options

                              OptionTypeDefault
                              debug
                              booleanfalse
                              position
                              Positionbottom
                              duration
                              number0
                              drag.disabled
                              booleanfalse
                              drag.direction
                              string | string[]
                              auto
                              scrollLock
                              boolean | objectobject
                              scrollLock.padding
                              booleantrue
                              teleport.target
                              stringbody
                              teleport.disabled
                              booleanfalse
                              transition
                              stringmagic-toast
                              layout.expand
                              string | false
                              click
                              layout.max
                              number3
                              animation.snap.duration
                              number300
                              animation.snap.easing
                              function
                              initial.expanded
                              booleanfalse
                              threshold.lock
                              number8
                              threshold.distancenumber32
                              threshold.momentum
                              number1

                              CSS Variables

                              VariableDefault
                              --magic-toast-padding-y1rem
                              --magic-toast-padding-x1rem
                              --magic-toast-gap0.75rem
                              --magic-toast-animation-duration175ms
                              --magic-toast-scale-factor0.05
                              --magic-toast-overlap-y1rem
                              --magic-toast-positionfixed
                              --magic-toast-inset0
                              --magic-toast-width100%
                              --magic-toast-height100%
                              --magic-toast-z-index999

                              MagicToastView

                              Renders a single toast inside the toaster. Used internally.

                              VariableDefault
                              --magic-toast-view-transitionall var(--magic-toast-animation-duration) var(--ease-in-out)
                              --magic-toast-view-cursorgrab
                              --magic-toast-view-cursor-dragginggrabbing

                              useMagicToast

                              Interact with a toaster instance from anywhere in your app. Pass the same id used on the corresponding MagicToastProvider.

                              js
                              const {
                                add,
                                remove,
                                clear,
                                hide,
                                show,
                                expand,
                                collapse,
                                toasts,
                                count,
                                hidden,
                              } = useMagicToast('your-toast-id')

                              add

                              Adds a toast to the stack and returns its id.

                              ArgumentTypeRequired
                              component
                              Componenttrue
                              props
                              Record<string, unknown>false
                              slots
                              Slotsfalse
                              options
                              MagicToastAddOptionsundefined
                              id
                              stringfalse
                              js
                              const id = add({ component, props: { message: 'Saved!' } })

                              remove

                              Removes a toast by id.

                              js
                              remove(id)

                              clear

                              Removes all toasts, including any currently hidden via hide(). Optionally pass a transition name to use while clearing, instead of the toaster’s configured transition option.

                              js
                              clear()
                              clear('my-clear-transition')

                              hide / show

                              Temporarily hide the entire toast stack and restore it later, preserving each toast’s state (props, timers, etc.) in between. Auto-dismiss timers are paused while hidden and resume when shown again. Both optionally take a transition name to use instead of the toaster’s configured transition option. Calling hide() with nothing to hide, or show() with nothing hidden, is a no-op.

                              Calling add() while the stack is hidden reveals it again immediately, so a new toast is never silently queued out of sight — it’s equivalent to calling show() first.

                              js
                              hide()
                              show()
                              
                              hide('my-hide-transition')
                              show('my-show-transition')

                              expand / collapse

                              Expand or collapse the toast stack, mirroring what layout.expand: 'click' | 'hover' does on interaction.

                              js
                              expand()
                              collapse()

                              State

                              PropertyTypeDescription
                              toastsComputedRef<ToastView[]>The currently active toasts.
                              countComputedRef<number>Number of currently active toasts.
                              hiddenComputedRef<number>Number of toasts currently stashed via hide(). Useful for disabling hide()/show() controls when there’s nothing to hide or restore.

                              Events

                              The toaster emits the following events through MagicEmitter. Listen to them with useMagicEmitter.

                              EventPayloadDescription
                              beforeEnteridFired before a toast’s enter transition starts.
                              enteridFired when a toast’s enter transition starts.
                              afterEnteridFired after a toast’s enter transition ends.
                              beforeLeaveidFired before a toast’s leave transition starts.
                              leaveidFired when a toast’s leave transition starts.
                              afterLeaveidFired after a toast’s leave transition ends.
                              beforeDrag{ id, x, y }Fired when a toast starts being dragged.
                              drag{ id, x, y }Fired continuously while a toast is dragged. x and y are the current translation in pixels.
                              afterDrag{ id, x, y }Fired when a toast stops being dragged.

                              Errors

                              SourceError CodeMessage
                              MagicToastViewmissing_instance_idMagicToastView must be used within a MagicToastProvider

                              Examples

                              Position

                              Set the position option to anchor the toaster to any edge or corner of the viewport.

                              <template>
                                <div class="w-full flex gap-2">
                                  <m-button @click="onClick">Add Toast</m-button>
                                  <m-select
                                    v-model="position"
                                    :options="options"
                                    label="Position"
                                    placeholder="Position"
                                  />
                                </div>
                                <magic-toast-provider
                                  id="magic-toast-position-demo"
                                  :options="{
                                    position,
                                  }"
                                />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton, MSelect } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-position-demo')
                              
                              const position = ref('bottom-right')
                              
                              const options = [
                                { value: 'top-right', label: 'Top Right' },
                                { value: 'top', label: 'Top' },
                                { value: 'top-left', label: 'Top Left' },
                                { value: 'left', label: 'Left' },
                                { value: 'bottom-left', label: 'Bottom Left' },
                                { value: 'bottom', label: 'Bottom' },
                                { value: 'bottom-right', label: 'Bottom Right' },
                                { value: 'right', label: 'Right' },
                              ]
                              
                              function onClick() {
                                const props = {
                                  message: options.find((p) => p.value === position.value)?.label,
                                }
                              
                                add({ component, props })
                              }
                              </script>

                              Expanded

                              Set initial.expanded: true together with layout.expand: false to always render the stack fully expanded, instead of collapsed into an overlapping pile.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-expanded-demo" :options="options" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-expanded-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              
                              const options = {
                                layout: {
                                  expand: false,
                                },
                                initial: {
                                  expanded: true,
                                },
                              }
                              </script>

                              Collapsed

                              Set layout.expand: false to keep the stack collapsed permanently, with no click or hover interaction to expand it.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-collapsed-demo" :options="options" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-collapsed-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              
                              const options = {
                                layout: {
                                  expand: false,
                                },
                              }
                              </script>

                              Hover

                              Set layout.expand: 'hover' to expand the stack while the pointer is over it, and collapse it again on mouse leave.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-hover-demo" :options="options" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-hover-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              
                              const options = {
                                layout: {
                                  expand: 'hover',
                                },
                              }
                              </script>

                              No Drag

                              Set drag: { disabled: true } on the provider to disable drag-to-dismiss for every toast in the stack.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-no-drag-demo" :options="options" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-no-drag-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              
                              const options = {
                                drag: { disabled: true },
                              }
                              </script>

                              Per-Toast Options

                              Pass options to add() to override provider defaults for a single toast, without affecting the rest of the stack. It accepts the per-toast subset of the toaster options — duration, drag, threshold and animation.

                              <template>
                                <div class="grid w-full grid-cols-2 items-end gap-3 sm:grid-cols-3">
                                  <m-toggle v-model="draggable" label="Draggable" />
                                  <m-select
                                    v-model="direction"
                                    :options="directionOptions"
                                    label="Drag direction"
                                    placeholder="Drag direction"
                                  />
                                  <m-input v-model="duration" type="number" label="Auto-dismiss (ms)" />
                                  <m-input v-model="distance" type="number" label="Dismiss distance (px)" />
                                  <m-input v-model="snapDuration" type="number" label="Snap duration (ms)" />
                                  <m-button class="w-full" @click="onClick">Add Toast</m-button>
                                </div>
                                <magic-toast-provider
                                  :id="id"
                                  :options="{
                                    position: 'bottom-right',
                                    layout: { expand: false, max: 10 },
                                    initial: { expanded: true },
                                  }"
                                />
                              </template>
                              
                              <script lang="ts" setup>
                              import { computed, defineAsyncComponent, shallowRef } from 'vue'
                              import { MButton, MInput, MSelect, MToggle } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              import type { MagicToastAddOptions } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const id = 'magic-toast-per-toast-options-demo'
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast(id)
                              
                              const draggable = shallowRef(true)
                              const duration = shallowRef(0)
                              const distance = shallowRef(32)
                              const snapDuration = shallowRef(300)
                              const direction = shallowRef('auto')
                              
                              const directionOptions = [
                                { value: 'auto', label: 'Auto' },
                                { value: 'left', label: 'Left' },
                                { value: 'right', label: 'Right' },
                                { value: 'up', label: 'Up' },
                                { value: 'down', label: 'Down' },
                                { value: 'left-right', label: 'Left & Right' },
                                { value: 'up-down', label: 'Up & Down' },
                              ]
                              
                              type Direction = NonNullable<
                                NonNullable<MagicToastAddOptions['drag']>['direction']
                              >
                              const resolvedDirection = computed<Direction>(() => {
                                switch (direction.value) {
                                  case 'left-right':
                                    return ['left', 'right']
                                  case 'up-down':
                                    return ['up', 'down']
                                  case 'left':
                                  case 'right':
                                  case 'up':
                                  case 'down':
                                    return direction.value
                                  default:
                                    return 'auto'
                                }
                              })
                              
                              function onClick() {
                                add({
                                  component,
                                  props: { message: draggable.value ? 'Drag me around' : 'Not draggable' },
                                  options: {
                                    duration: Number(duration.value),
                                    drag: {
                                      disabled: !draggable.value,
                                      direction: resolvedDirection.value,
                                    },
                                    threshold: { distance: Number(distance.value) },
                                    animation: { snap: { duration: Number(snapDuration.value) } },
                                  },
                                })
                              }
                              </script>

                              Drag Direction

                              Use drag.direction to pin the drag-out side ('left' | 'right' | 'up' | 'down') regardless of position, or pass a same-axis pair like ['left', 'right'] to allow dragging either way.

                              <template>
                                <div class="flex w-full gap-2">
                                  <m-button @click="onClick">Add Toast</m-button>
                                  <m-select
                                    v-model="position"
                                    :options="positionOptions"
                                    label="Position"
                                    placeholder="Position"
                                  />
                                  <m-select
                                    v-model="direction"
                                    :options="directionOptions"
                                    label="Drag direction"
                                    placeholder="Drag direction"
                                  />
                                </div>
                                <magic-toast-provider
                                  id="magic-toast-drag-direction-demo"
                                  :options="{
                                    position,
                                    drag: { direction: resolvedDirection },
                                    layout: {
                                      expand: false,
                                      max: 10,
                                    },
                                    initial: {
                                      expanded: true,
                                    },
                                  }"
                                />
                              </template>
                              
                              <script lang="ts" setup>
                              import { computed, defineAsyncComponent, ref } from 'vue'
                              import { MButton, MSelect } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add } = useMagicToast('magic-toast-drag-direction-demo')
                              
                              const position = ref('bottom-right')
                              const direction = ref('left-right')
                              
                              const positionOptions = [
                                { value: 'top-right', label: 'Top Right' },
                                { value: 'top', label: 'Top' },
                                { value: 'top-left', label: 'Top Left' },
                                { value: 'left', label: 'Left' },
                                { value: 'bottom-left', label: 'Bottom Left' },
                                { value: 'bottom', label: 'Bottom' },
                                { value: 'bottom-right', label: 'Bottom Right' },
                                { value: 'right', label: 'Right' },
                              ]
                              
                              const directionOptions = [
                                { value: 'auto', label: 'Auto' },
                                { value: 'left', label: 'Left' },
                                { value: 'right', label: 'Right' },
                                { value: 'up', label: 'Up' },
                                { value: 'down', label: 'Down' },
                                { value: 'left-right', label: 'Left & Right' },
                                { value: 'up-down', label: 'Up & Down' },
                              ]
                              
                              // MSelect only supports a single value, so the same-axis pairs are
                              // offered as presets here and expanded into an array for the option.
                              const resolvedDirection = computed(() => {
                                if (direction.value === 'left-right') {
                                  return ['left', 'right'] as const
                                }
                              
                                if (direction.value === 'up-down') {
                                  return ['up', 'down'] as const
                                }
                              
                                return direction.value
                              })
                              
                              // Mirrors the fallback in useToastDrag: when direction is 'auto',
                              // the actual drag axis/side is derived from the anchor position.
                              const messageDirection = computed(() => {
                                if (direction.value === 'left-right') {
                                  return 'left or right'
                                }
                              
                                if (direction.value === 'up-down') {
                                  return 'up or down'
                                }
                              
                                if (direction.value !== 'auto') {
                                  return direction.value
                                }
                              
                                switch (position.value) {
                                  case 'top':
                                  case 'top-left':
                                  case 'top-right':
                                    return 'up'
                                  case 'bottom':
                                  case 'bottom-left':
                                  case 'bottom-right':
                                    return 'down'
                                  case 'left':
                                    return 'left'
                                  case 'right':
                                    return 'right'
                                  default:
                                    return direction.value
                                }
                              })
                              
                              function onClick() {
                                add({
                                  component,
                                  props: { message: `Drag me ${messageDirection.value} to dismiss` },
                                })
                              }
                              </script>

                              Opacity Fade

                              The toast does not fade on its own. Listen to the drag event, derive an opacity from the drag distance, and reset it on afterDrag.

                              <template>
                                <div class="flex w-full gap-2">
                                  <m-button @click="onClick">Add Toast</m-button>
                                </div>
                                <magic-toast-provider
                                  :id="id"
                                  :options="{
                                    position: 'bottom-right',
                                    threshold: { distance: dismissThreshold },
                                    layout: { expand: false, max: 1 },
                                    initial: { expanded: true },
                                  }"
                                />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, reactive, onBeforeUnmount } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              import { useMagicEmitter } from '@maas/vue-equipment/plugins/MagicEmitter'
                              import type { MagicEmitterEvents } from '@maas/vue-equipment/plugins/MagicEmitter'
                              
                              const id = 'magic-toast-opacity-fade-demo'
                              const component = defineAsyncComponent(
                                () => import('./components/FadeDemoToast.vue')
                              )
                              
                              const { add } = useMagicToast(id)
                              const emitter = useMagicEmitter()
                              
                              // Distance that dismisses the toast; the fade spans four times that
                              const dismissThreshold = 60
                              const fadeDistance = dismissThreshold * 4
                              
                              const props = reactive({ message: 'Drag me away to fade me out', opacity: 1 })
                              
                              // drag is shared across plugins, so the payload is a union — narrow it to the
                              // x/y shape before use. Derive opacity from the drag distance and reset it once
                              // the drag ends, entirely through the emitter — the toast no longer fades on its own.
                              function onDrag(payload: MagicEmitterEvents['drag']) {
                                if (payload.id !== id || !('x' in payload)) {
                                  return
                                }
                              
                                const distance = Math.max(Math.abs(payload.x), Math.abs(payload.y))
                                props.opacity = 1 - Math.min(distance / fadeDistance, 1)
                              }
                              
                              function onAfterDrag(payload: MagicEmitterEvents['afterDrag']) {
                                if (payload.id !== id || !('x' in payload)) {
                                  return
                                }
                              
                                props.opacity = 1
                              }
                              
                              emitter.on('drag', onDrag)
                              emitter.on('afterDrag', onAfterDrag)
                              
                              onBeforeUnmount(() => {
                                emitter.off('drag', onDrag)
                                emitter.off('afterDrag', onAfterDrag)
                              })
                              
                              function onClick() {
                                add({ component, props })
                              }
                              </script>

                              Clear All

                              Call clear() to remove every toast in the stack at once, optionally with a custom transition name.

                              <template>
                                <div class="flex gap-2">
                                  <m-button @click="onClick">Add Toast</m-button>
                                  <m-button @click="clear">Clear All</m-button>
                                </div>
                                <magic-toast-provider id="magic-toast-clear-all-demo" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const { add, clear } = useMagicToast('magic-toast-clear-all-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              </script>

                              Hide and Show

                              Call hide() to temporarily remove the whole stack from view, and show() to restore it exactly as it was — props, timers and all.

                              <template>
                                <div class="flex gap-2">
                                  <m-button @click="onClick">Add Toast</m-button>
                                  <m-button :disabled="toastCount === 0" @click="hide">Hide</m-button>
                                  <m-button :disabled="hidden === 0" @click="show">Show</m-button>
                                </div>
                                <magic-toast-provider
                                  id="magic-toast-hide-show-demo"
                                  :options="{
                                    layout: {
                                      expand: false,
                                      max: 10,
                                    },
                                    initial: {
                                      expanded: true,
                                    },
                                  }"
                                />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const {
                                add,
                                hide,
                                show,
                                count: toastCount,
                                hidden,
                              } = useMagicToast('magic-toast-hide-show-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              </script>

                              Hide and Show with a Custom Transition

                              Pass a transition name to hide()/show() to swap in a different animation just for that call, without changing the toaster’s configured transition option.

                              <template>
                                <div class="flex gap-2">
                                  <m-button @click="onClick">Add Toast</m-button>
                                  <m-button :disabled="toastCount === 0" @click="hide('zoom')">
                                    Hide (zoom)
                                  </m-button>
                                  <m-button :disabled="hidden === 0" @click="show('zoom')">
                                    Show (zoom)
                                  </m-button>
                                </div>
                                <magic-toast-provider
                                  id="magic-toast-hide-show-transition-demo"
                                  :options="{
                                    layout: {
                                      expand: false,
                                      max: 10,
                                    },
                                    initial: {
                                      expanded: true,
                                    },
                                  }"
                                />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              import '@maas/vue-equipment/utils/css/keyframes/zoom-in.css'
                              import '@maas/vue-equipment/utils/css/keyframes/zoom-out.css'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              const {
                                add,
                                hide,
                                show,
                                count: toastCount,
                                hidden,
                              } = useMagicToast('magic-toast-hide-show-transition-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                const props = {
                                  message: count.value % 2 ? 'Magic as a Service™' : 'Vue Equipment',
                                }
                              
                                add({ component, props })
                              }
                              </script>
                              
                              <style>
                              /* Custom transition used only for hide('zoom') / show('zoom'),
                                 passed as the transition name override on those calls. */
                              .zoom-enter-active {
                                animation: zoom-in var(--magic-toast-animation-duration) var(--ease-in-out);
                              }
                              
                              .zoom-leave-active {
                                animation: zoom-out var(--magic-toast-animation-duration) var(--ease-in-out);
                                position: absolute;
                              }
                              
                              .zoom-move {
                                transition: all var(--magic-toast-animation-duration) var(--ease-in-out);
                              }
                              </style>

                              Slot

                              Pass slots to add() to render arbitrary content inside the toast component via its default slot.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-slot-demo" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref, h, type Slots } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              
                              const { add } = useMagicToast('magic-toast-slot-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                // Break reactivity for count
                                const mappedCount = count.value
                              
                                const slots: Slots = {
                                  default: () => [h('span', `Message #${mappedCount}`)],
                                }
                              
                                add({ component, slots })
                              }
                              </script>

                              Slotted Component

                              Pass a component (instead of plain content) through slots, so the toast can render nested, composed markup.

                              <template>
                                <m-button @click="onClick">Add Toast</m-button>
                                <magic-toast-provider id="magic-toast-nested-slot-demo" />
                              </template>
                              
                              <script lang="ts" setup>
                              import { defineAsyncComponent, ref, h, type Slots } from 'vue'
                              import { MButton } from '@maas/mirror/vue'
                              import { useMagicToast } from '@maas/vue-equipment/plugins/MagicToast'
                              
                              const count = ref(0)
                              
                              const component = defineAsyncComponent(
                                () => import('./components/DemoToast.vue')
                              )
                              
                              const slot = defineAsyncComponent(() => import('./components/DemoSlot.vue'))
                              
                              const { add } = useMagicToast('magic-toast-nested-slot-demo')
                              
                              function onClick() {
                                count.value += 1
                              
                                // Break reactivity for count
                                const mappedCount = count.value
                              
                                const slots: Slots = {
                                  default: () => [h(slot, { message: `Component #${mappedCount}` })],
                                }
                              
                                add({ component, slots })
                              }
                              </script>