# Toast

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
---

<div class="flex flex-wrap gap-2">
  <Button variant="outline" id="toast-demo-default">Default</Button>
  <Button variant="outline" id="toast-demo-success">Success</Button>
  <Button variant="outline" id="toast-demo-error">Error</Button>
</div>

<script>
  import { toast } from "@/components/starwind/toast";

  document.getElementById("toast-demo-default")?.addEventListener("click", () => {
    toast("Default Toast");
  });

  document.getElementById("toast-demo-success")?.addEventListener("click", () => {
    toast.success("Success!", { description: "Your changes have been saved." });
  });

  document.getElementById("toast-demo-error")?.addEventListener("click", () => {
    toast.error("Error", { description: "Something went wrong." });
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import { Button } from "@/components/starwind/button";
import { toast } from "@/components/starwind/toast";

export function Example() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button variant="outline" onClick={() => toast("Default Toast")}>Default</Button>
      <Button variant="outline" onClick={() => toast.success("Success!", { description: "Your changes have been saved." })}>Success</Button>
      <Button variant="outline" onClick={() => toast.error("Error", { description: "Something went wrong." })}>Error</Button>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { toast, Toaster } from "@/components/starwind/toast";

function showToast1() {
  toast("Default Toast");
}

function showToast2() {
  toast.success("Success!", { description: "Your changes have been saved." });
}

function showToast3() {
  toast.error("Error", { description: "Something went wrong." });
}
</script>

<template>
  <div class="flex flex-wrap gap-2">
    <Button variant="outline" @click="showToast1">Default</Button>
    <Button variant="outline" @click="showToast2">Success</Button>
    <Button variant="outline" @click="showToast3">Error</Button>
  </div>
  <Toaster position="bottom-right" />
</template>
```
  </div>
</FrameworkCodeSwitcher>

> **Info:** The local Toast component re-exports `toast`, so styled parts and imperative notifications use
the same `@/components/starwind/toast` import path.

## Installation

```bash
npx starwind@latest add toast --framework astro
```
</DocsTabsContent>
```bash
npx starwind@latest add toast --framework react
```
</DocsTabsContent>
```bash
npx starwind@latest add toast --framework vue
```
</DocsTabsContent>
</DocsTabs>

## Usage

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
---

<div class="flex flex-wrap gap-2">
  <Button variant="outline" id="toast-demo-default">Default</Button>
  <Button variant="outline" id="toast-demo-success">Success</Button>
  <Button variant="outline" id="toast-demo-error">Error</Button>
</div>

<script>
  import { toast } from "@/components/starwind/toast";

  document.getElementById("toast-demo-default")?.addEventListener("click", () => {
    toast("Default Toast");
  });

  document.getElementById("toast-demo-success")?.addEventListener("click", () => {
    toast.success("Success!", { description: "Your changes have been saved." });
  });

  document.getElementById("toast-demo-error")?.addEventListener("click", () => {
    toast.error("Error", { description: "Something went wrong." });
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import { Button } from "@/components/starwind/button";
import { toast } from "@/components/starwind/toast";

export function Example() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button variant="outline" onClick={() => toast("Default Toast")}>Default</Button>
      <Button variant="outline" onClick={() => toast.success("Success!", { description: "Your changes have been saved." })}>Success</Button>
      <Button variant="outline" onClick={() => toast.error("Error", { description: "Something went wrong." })}>Error</Button>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { toast, Toaster } from "@/components/starwind/toast";

function showToast1() {
  toast("Default Toast");
}

function showToast2() {
  toast.success("Success!", { description: "Your changes have been saved." });
}

function showToast3() {
  toast.error("Error", { description: "Something went wrong." });
}
</script>

<template>
  <div class="flex flex-wrap gap-2">
    <Button variant="outline" @click="showToast1">Default</Button>
    <Button variant="outline" @click="showToast2">Success</Button>
    <Button variant="outline" @click="showToast3">Error</Button>
  </div>
  <Toaster position="bottom-right" />
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Setup

Render `Toaster` once near the application root so notifications can appear from any route.

<FrameworkCodeSwitcher>
<div slot="astro">
```astro title="src/layouts/Layout.astro"
---
import { Toaster } from "@/components/starwind/toast";
---

<!doctype html>
<html lang="en">
  <head>
    <!-- ... -->
  </head>
  <body>
    <main>
      <slot />
    </main>
    <Toaster position="bottom-right" />
  </body>
</html>
```
</div>
<div slot="react">
```tsx title="src/App.tsx"
import type { ReactNode } from "react";
import { Toaster } from "@/components/starwind/toast";

export function App({ children }: { children: ReactNode }) {
  return (
    <>
      <main>{children}</main>
      <Toaster position="bottom-right" />
    </>
  );
}
```
</div>
<div slot="vue">
```vue
<script setup lang="ts">
import { Toaster } from "@/components/starwind/toast";
</script>

<template>
  <main><slot /></main>
  <Toaster position="bottom-right" />
</template>
```
</div>
</FrameworkCodeSwitcher>

## Basic Usage

Toasts are created using the `toast` function. Import it in a `<script>` tag and call it to show notifications.

<FrameworkCodeSwitcher>
<div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
---

<Button id="show-toast">Show Toast</Button>

<script>
  import { toast } from "@/components/starwind/toast";

  document.getElementById("show-toast")?.addEventListener("click", () => {
    toast("Hello world!");
  });
</script>
```
</div>
<div slot="react">
```tsx
import { Button } from "@/components/starwind/button";
import { toast } from "@/components/starwind/toast";

export function Example() {
  return <Button onClick={() => toast("Hello world!")}>Show Toast</Button>;
}
```
</div>
<div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { toast, Toaster } from "@/components/starwind/toast";

function showToast1() {
  toast("Hello world!");
}
</script>

<template>
  <Button @click="showToast1">Show Toast</Button>
  <Toaster position="bottom-right" />
</template>
```
</div>
</FrameworkCodeSwitcher>

## Variants

The toast system supports multiple variants for different message types.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
---

<div class="flex flex-wrap gap-2">
  <Button variant="outline" id="toast-default">Default</Button>
  <Button variant="outline" id="toast-success">Success</Button>
  <Button variant="outline" id="toast-error">Error</Button>
  <Button variant="outline" id="toast-warning">Warning</Button>
  <Button variant="outline" id="toast-info">Info</Button>
  <Button variant="outline" id="toast-loading">Loading</Button>
</div>

<script>
  import { toast } from "@/components/starwind/toast";

  document.getElementById("toast-default")?.addEventListener("click", () => {
    toast("Default Toast");
  });

  document.getElementById("toast-success")?.addEventListener("click", () => {
    toast.success("Success!", {
      description: "Your changes have been saved.",
    });
  });

  document.getElementById("toast-error")?.addEventListener("click", () => {
    toast.error("Error", {
      description: "Something went wrong.",
    });
  });

  document.getElementById("toast-warning")?.addEventListener("click", () => {
    toast.warning("Warning", {
      description: "Please review your input.",
    });
  });

  document.getElementById("toast-info")?.addEventListener("click", () => {
    toast.info("Info", {
      description: "Here's some helpful information.",
    });
  });

  document.getElementById("toast-loading")?.addEventListener("click", () => {
    toast.loading("Loading...", {
      description: "Please wait while we process your request.",
    });
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import { Button } from "@/components/starwind/button";
import { toast } from "@/components/starwind/toast";

export function Example() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button variant="outline" onClick={() => toast("Default Toast")}>Default</Button>
      <Button
        variant="outline"
        onClick={() => toast.success("Success!", { description: "Your changes have been saved." })}
      >
        Success
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.error("Error", { description: "Something went wrong." })}
      >
        Error
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.warning("Warning", { description: "Please review your input." })}
      >
        Warning
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.info("Info", { description: "Here's some helpful information." })}
      >
        Info
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.loading("Loading...", { description: "Please wait while we process your request." })}
      >
        Loading
      </Button>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { toast, Toaster } from "@/components/starwind/toast";

function showToast1() {
  toast("Default Toast");
}

function showToast2() {
  toast.success("Success!", {
    description: "Your changes have been saved.",
  });
}

function showToast3() {
  toast.error("Error", {
    description: "Something went wrong.",
  });
}

function showToast4() {
  toast.warning("Warning", {
    description: "Please review your input.",
  });
}

function showToast5() {
  toast.info("Info", {
    description: "Here's some helpful information.",
  });
}

function showToast6() {
  toast.loading("Loading...", {
    description: "Please wait while we process your request.",
  });
}
</script>

<template>
  <div class="flex flex-wrap gap-2">
    <Button variant="outline" @click="showToast1">Default</Button>
    <Button variant="outline" @click="showToast2">Success</Button>
    <Button variant="outline" @click="showToast3">Error</Button>
    <Button variant="outline" @click="showToast4">Warning</Button>
    <Button variant="outline" @click="showToast5">Info</Button>
    <Button variant="outline" @click="showToast6">Loading</Button>
  </div>
  <Toaster position="bottom-right" />
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Promise Toast

Handle async operations with automatic loading, success, and error states.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
---

<div class="flex flex-wrap gap-2">
  <Button variant="primary" id="toast-promise-success">Promise (Success)</Button>
  <Button variant="error" id="toast-promise-error">Promise (Error)</Button>
</div>

<script>
  import { toast } from "@/components/starwind/toast";

  document.getElementById("toast-promise-success")?.addEventListener("click", () => {
    const fakeApiCall = async () => {
      await new Promise((resolve) => setTimeout(resolve, 2000));
      return { name: "John" };
    };

    toast.promise(fakeApiCall(), {
      loading: { title: "Saving...", description: "Please wait" },
      success: (data) => ({ title: "Saved!", description: `Welcome, ${data.name}!` }),
      error: { title: "Error", description: "Failed to save" },
    });
  });

  document.getElementById("toast-promise-error")?.addEventListener("click", () => {
    const fakeApiCall = async () => {
      await new Promise((resolve) => setTimeout(resolve, 2000));
      throw new Error("Network error");
    };

    toast
      .promise(fakeApiCall(), {
        loading: "Processing...",
        success: "Done!",
        error: (err) => ({
          title: err.message || "Contact support for assistance",
          description: "Pardon our dust while we fix this issue.",
        }),
      })
      .catch(() => {});
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import { Button } from "@/components/starwind/button";
import { toast } from "@/components/starwind/toast";

async function successfulRequest() {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  return { name: "John" };
}

async function failedRequest() {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  throw new Error("Network error");
}

export function Example() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button
        variant="primary"
        onClick={() => {
          void toast.promise(successfulRequest(), {
            loading: { title: "Saving...", description: "Please wait" },
            success: (data) => ({ title: "Saved!", description: "Welcome, " + data.name + "!" }),
            error: { title: "Error", description: "Failed to save" },
          });
        }}
      >
        Promise (Success)
      </Button>
      <Button
        variant="error"
        onClick={() => {
          void toast
            .promise(failedRequest(), {
              loading: "Processing...",
              success: "Done!",
              error: (error) => ({
                title: error instanceof Error ? error.message : "Contact support for assistance",
                description: "Pardon our dust while we fix this issue.",
              }),
            })
            .catch(() => {});
        }}
      >
        Promise (Error)
      </Button>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { toast, Toaster } from "@/components/starwind/toast";

function showToast1() {
  const fakeApiCall = async () => {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    return { name: "John" };
  };

  toast.promise(fakeApiCall(), {
    loading: { title: "Saving...", description: "Please wait" },
    success: (data) => ({ title: "Saved!", description: `Welcome, ${data.name}!` }),
    error: { title: "Error", description: "Failed to save" },
  });
}

function showToast2() {
  const fakeApiCall = async () => {
    await new Promise((resolve) => setTimeout(resolve, 2000));
    throw new Error("Network error");
  };

  toast
    .promise(fakeApiCall(), {
      loading: "Processing...",
      success: "Done!",
      error: (err) => ({
        title: err.message || "Contact support for assistance",
        description: "Pardon our dust while we fix this issue.",
      }),
    })
    .catch(() => {});
}
</script>

<template>
  <div class="flex flex-wrap gap-2">
    <Button variant="primary" @click="showToast1">Promise (Success)</Button>
    <Button variant="error" @click="showToast2">Promise (Error)</Button>
  </div>
  <Toaster position="bottom-right" />
</template>
```
  </div>
</FrameworkCodeSwitcher>

## Updating & Dismissing

You can update existing toasts or dismiss them programmatically.

<FrameworkCodeSwitcher>
  <div slot="astro">
```astro
---
import { Button } from "@/components/starwind/button";
---

<div class="flex flex-wrap gap-2">
  <Button variant="outline" id="toast-update">Create & Update</Button>
  <Button variant="outline" id="toast-dismiss-all">Dismiss All</Button>
</div>

<script>
  import { toast } from "@/components/starwind/toast";

  document.getElementById("toast-update")?.addEventListener("click", () => {
    const id = toast("Processing...", { description: "Step 1 of 3" });

    setTimeout(() => {
      toast.update(id, { title: "Still working...", description: "Step 2 of 3" });
    }, 1500);

    setTimeout(() => {
      toast.update(id, {
        title: "Complete!",
        description: "All steps finished",
        variant: "success",
      });
    }, 3000);
  });

  document.getElementById("toast-dismiss-all")?.addEventListener("click", () => {
    toast.dismiss();
  });
</script>
```
  </div>
  <div slot="react">
```tsx
import { Button } from "@/components/starwind/button";
import { toast } from "@/components/starwind/toast";

function createAndUpdateToast() {
  const id = toast("Processing...", { description: "Step 1 of 3" });
  setTimeout(() => {
    toast.update(id, { title: "Still working...", description: "Step 2 of 3" });
  }, 1500);
  setTimeout(() => {
    toast.update(id, {
      title: "Complete!",
      description: "All steps finished",
      variant: "success",
    });
  }, 3000);
}

export function Example() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button variant="outline" onClick={createAndUpdateToast}>Create & Update</Button>
      <Button variant="outline" onClick={() => toast.dismiss()}>Dismiss All</Button>
    </div>
  );
}
```
  </div>
  <div slot="vue">
```vue
<script setup lang="ts">
import { Button } from "@/components/starwind/button";
import { toast, Toaster } from "@/components/starwind/toast";

function showToast1() {
  const id = toast("Processing...", { description: "Step 1 of 3" });

  setTimeout(() => {
    toast.update(id, { title: "Still working...", description: "Step 2 of 3" });
  }, 1500);

  setTimeout(() => {
    toast.update(id, {
      title: "Complete!",
      description: "All steps finished",
      variant: "success",
    });
  }, 3000);
}

function showToast2() {
  toast.dismiss();
}
</script>

<template>
  <div class="flex flex-wrap gap-2">
    <Button variant="outline" @click="showToast1">Create & Update</Button>
    <Button variant="outline" @click="showToast2">Dismiss All</Button>
  </div>
  <Toaster position="bottom-right" />
</template>
```
  </div>
</FrameworkCodeSwitcher>

## API Reference
### Toaster
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `gap` | `string` | No | `"0.5rem"` | Wrapper prop | Sets the space between repeated items. |
| `peek` | `string` | No | `"1rem"` | Wrapper prop | Sets how much of an adjacent item remains visible. |
- Inherits div attributes.

### ToastTemplate
- Inherits div attributes.

### ToastItem
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `variant` | `"default" \| "success" \| "error" \| "warning" \| "info"` | No | `"default"` | Styled variant | Selects the component's visual variant. |
- Inherits div attributes.

### ToastContent
- Inherits div attributes.

### ToastTitle
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `variant` | `"default" \| "success" \| "error" \| "warning" \| "info" \| "loading"` | No | `"default"` | Styled variant | Selects the component's visual variant. |
- Inherits div attributes.

### ToastDescription
- Inherits div attributes.

### ToastAction
- Inherits button attributes.

### ToastClose
| Prop | Type | Required | Default | Kind | Description |
| --- | --- | --- | --- | --- | --- |
| `showIcon` | `boolean` | No | `true` | Wrapper prop | Shows the component's generated icon. |
- Inherits button attributes.
### Primitive And Runtime API
Behavior, state, events, form participation, and imperative methods are documented in the lower-level references.
- Primitive: [Toast Primitive](/docs/primitives/toast/)
- Runtime factory: [`createToastManager`](/docs/runtime/#create-toast-manager) from `@starwind-ui/runtime/toast`

## Changelog

### v2.1.0

- Re-exported `toast` and its public types from the local Toast component barrel so imperative
notifications and styled parts can use the same import path.

### v2.0.1

- Named the generated aggregate default export so React and Astro tooling can identify the installed component cleanly.

### v2.0.0

- Rebuilt Toast on Starwind Runtime for manager state, templates, updates, dismissal, and lifecycle.
- See the [Toast Primitive](/docs/primitives/toast/) for the underlying unstyled anatomy and behavior API.
- The styled package supplies the Toaster markup, while imperative notifications now come from the framework primitive entrypoint: `@starwind-ui/astro/toast`.