Skip to content

Toaster — usage examples ​

Toaster ships as six pre-compiled, per-framework packages from a single .rozie source — install only the one for your framework (no Rozie toolchain, no build-time compile step). Each carries its engine + framework peers as peer dependencies, so you control their versions. The snippets below are the same idiomatic consumption code shown in each package's README; switch the tab to your framework.

Usage ​

tsx
import { useRef } from 'react';
import { Toaster, type ToasterHandle } from '@rozie-ui/toast-react';

export function Demo() {
  const toaster = useRef<ToasterHandle>(null);
  // An action button on the toast; `data` rides along to the callback and the `dismissed` event.
  const archive = () =>
    toaster.current?.show({
      message: 'Conversation archived',
      data: { threadId: 't42' },
      action: { label: 'Undo', onClick: (ctx) => restore(ctx.data.threadId) },
    });
  return (
    <>
      <button onClick={() => toaster.current?.show({ message: 'Saved!', type: 'success' })}>
        Save
      </button>
      <button onClick={() => toaster.current?.show({ message: 'Something failed', type: 'error' })}>
        Fail
      </button>
      <button onClick={archive}>Archive</button>

      {/* Mount the host once (typically near the app root). */}
      <Toaster ref={toaster} position="bottom-right" duration={4000} />
    </>
  );
}

// Custom per-toast chrome via the #toast scoped slot — the `renderToast` prop
// (or `slots={{ toast: ... }}`), NOT children:
//   const renderToast = ({ toast, dismiss }) => (
//     <div className="my-toast">
//       <strong>{toast.type}</strong> {toast.message}
//       <button onClick={() => dismiss(toast.id)}>OK</button>
//     </div>
//   );
//   <Toaster ref={toaster} renderToast={renderToast} />
vue
<script setup lang="ts">
import { ref } from 'vue';
import Toaster from '@rozie-ui/toast-vue';

const toaster = ref();          // template ref → the imperative handle
</script>

<template>
  <button @click="toaster.show({ message: 'Saved!', type: 'success' })">Save</button>
  <button @click="toaster.show({ message: 'Something failed', type: 'error' })">Fail</button>
  <button @click="toaster.show({ message: 'Conversation archived', data: { threadId: 't42' }, action: { label: 'Undo', onClick: (ctx) => restore(ctx.data.threadId) } })">Archive</button>

  <!-- Mount the host once (typically near the app root). -->
  <Toaster ref="toaster" position="bottom-right" :duration="4000" />

  <!-- Custom per-toast chrome via the #toast scoped slot:
  <Toaster ref="toaster">
    <template #toast="{ toast, dismiss }">
      <strong>{{ toast.type }}</strong> {{ toast.message }}
      <button @click="dismiss(toast.id)">OK</button>
    </template>
  </Toaster>
  -->
</template>
svelte
<script lang="ts">
  import Toaster from '@rozie-ui/toast-svelte';

  let toaster;                  // component instance via bind:this
</script>

<button onclick={() => toaster.show({ message: 'Saved!', type: 'success' })}>Save</button>
<button onclick={() => toaster.show({ message: 'Something failed', type: 'error' })}>Fail</button>
<button onclick={() => toaster.show({ message: 'Conversation archived', data: { threadId: 't42' }, action: { label: 'Undo', onClick: (ctx) => restore(ctx.data.threadId) } })}>Archive</button>

<!-- Mount the host once (typically near the app root). -->
<Toaster bind:this={toaster} position="bottom-right" duration={4000} />
ts
import { Component, ViewChild } from '@angular/core';
import { Toaster } from '@rozie-ui/toast-angular';

@Component({
  selector: 'app-demo',
  standalone: true,
  imports: [Toaster],
  template: `
    <button (click)="toaster.show({ message: 'Saved!', type: 'success' })">Save</button>
    <button (click)="toaster.show({ message: 'Something failed', type: 'error' })">Fail</button>
    <button (click)="toaster.show({ message: 'Conversation archived', data: { threadId: 't42' }, action: { label: 'Undo', onClick: onUndo } })">Archive</button>

    <!-- Mount the host once (typically near the app root). -->
    <Toaster #toaster position="bottom-right" [duration]="4000" />
  `,
})
export class DemoComponent {
  @ViewChild('toaster') toaster!: Toaster;
  onUndo(ctx: { id: string; data: { threadId: string } }) { restore(ctx.data.threadId); }
}
tsx
import { Toaster, type ToasterHandle } from '@rozie-ui/toast-solid';

export function Demo() {
  let toaster: ToasterHandle | undefined;
  // The ref callback receives the HANDLE object (not the DOM node).
  // An action button on the toast; `data` rides along to the callback and the `dismissed` event.
  const archive = () =>
    toaster?.show({
      message: 'Conversation archived',
      data: { threadId: 't42' },
      action: { label: 'Undo', onClick: (ctx) => restore(ctx.data.threadId) },
    });
  return (
    <>
      <button onClick={() => toaster?.show({ message: 'Saved!', type: 'success' })}>Save</button>
      <button onClick={() => toaster?.show({ message: 'Something failed', type: 'error' })}>Fail</button>
      <button onClick={archive}>Archive</button>

      {/* Mount the host once (typically near the app root). */}
      <Toaster ref={(h) => (toaster = h)} position="bottom-right" duration={4000} />
      {/* Custom per-toast chrome via the #toast scoped slot — the `toastSlot` prop
          (or `slots={{ toast: ... }}`). Read the scope through `ctx` (its fields are
          getters) rather than destructuring it:
      const toastChrome = (ctx) => (
        <div class="my-toast">
          <strong>{ctx.toast.type}</strong> {ctx.toast.message}
          <button onClick={() => ctx.dismiss(ctx.toast.id)}>OK</button>
        </div>
      );
      <Toaster ref={(h) => (toaster = h)} toastSlot={toastChrome} /> */}
    </>
  );
}
ts
import '@rozie-ui/toast-lit';

// <rozie-toaster> is a custom element. Bind `position`/`duration` as properties,
// then call the imperative `show` / `dismiss` / `clear` methods on the element.
const el = document.querySelector('rozie-toaster');
el.position = 'bottom-right';
el.duration = 4000;
const id = el.show({ message: 'Saved!', type: 'success' });
// el.dismiss(id);
// el.clear();

// A toast with an action button + pass-through data:
el.show({
  message: 'Conversation archived',
  data: { threadId: 't42' },
  action: { label: 'Undo', onClick: (ctx) => restore(ctx.data.threadId) },
});

Imperative handle ​

Beyond props and events, Toaster exposes imperative methods (declared once in the .rozie source via $expose). Grab a handle through your framework's native ref mechanism and call them directly:

tsx
import { useRef } from 'react';
import { Toaster, type ToasterHandle } from '@rozie-ui/toast-react';

const toaster = useRef<ToasterHandle>(null);
// <Toaster ref={toaster} ... />
const id = toaster.current?.show({ message: 'Saved', type: 'success' });
toaster.current?.dismiss(id!);
toaster.current?.clear();
vue
<script setup>
import { ref } from 'vue';
const toaster = ref();          // template ref
</script>

<template>
  <Toaster ref="toaster" />
  <button @click="toaster.show({ message: 'Saved', type: 'success' })">Notify</button>
  <button @click="toaster.clear()">Clear all</button>
</template>
svelte
<script>
  let toaster;                  // component instance via bind:this
</script>

<Toaster bind:this={toaster} />
<button onclick={() => toaster.show({ message: 'Saved', type: 'success' })}>Notify</button>
<button onclick={() => toaster.clear()}>Clear all</button>
ts
@Component({ /* ... */ })
export class DemoComponent {
  @ViewChild(Toaster) toaster!: Toaster;   // or the viewChild() signal
  notify() { this.toaster.show({ message: 'Saved', type: 'success' }); }
  clearAll() { this.toaster.clear(); }
}
tsx
import { Toaster, type ToasterHandle } from '@rozie-ui/toast-solid';

let toaster: ToasterHandle | undefined;
// The ref callback receives the HANDLE object (not the DOM node).
<Toaster ref={(h) => (toaster = h)} />;
toaster?.show({ message: 'Saved', type: 'success' });
toaster?.clear();
ts
// The custom element IS the handle — the exposed methods are public element
// methods (none overrides an inherited HTMLElement member, so there is no
// ROZ137 warning).
const el = document.querySelector('rozie-toaster');
const id = el.show({ message: 'Saved', type: 'success' });
el.dismiss(id);
el.clear();

See also ​

Pre-1.0 — APIs may change between minor versions.