# Toaster

Brief, non-blocking messages about the result of an action, raised with toast() from sonner.

```tsx
import { toast } from "sonner"
import { Button } from "@zenoxai/ui/components/button"
import { Toaster } from "@zenoxai/ui/components/sonner"

function ToasterDemo() {
  return (
    <>
      <Toaster />
      <Button
        variant="outline"
        onClick={() => toast.success("Report exported")}
      >
        Export report
      </Button>
    </>
  )
}
```

## Usage

Mount `Toaster` once, near the root of the app, next to any other app-wide hosts:

```tsx
import { Toaster } from "@zenoxai/ui/components/sonner"

export function App() {
  return (
    <>
      <Routes />
      <Toaster />
    </>
  )
}
```

Then raise toasts from anywhere, including outside React components, with `toast` from
`sonner`:

```tsx
import { toast } from "sonner"

toast.success("Report exported")
toast.error("Could not reach the SIEM connector")
```

The examples on this page share the single `Toaster` rendered by the first example, the same way
an app shares the one at its root. Never mount a second one: each `Toaster` shows every toast,
so two would show them twice.

`Toaster` wraps sonner's component with the Zenox defaults: toasts stack in the top-right
corner, use the popover surface and border tokens, show the library's status icons, and follow
the `.dark` class on `<html>`, so no theme provider is needed. It accepts every
[sonner Toaster prop](https://sonner.emilkowal.ski/toaster) to change the position, the
duration or the number of visible toasts.

Use a toast to confirm that something happened, or failed, without stopping the user: "Report
exported", "Alert assigned". Write it in the past tense, in one line.

- For a message that must stay on screen until the user deals with it, use an
  [Alert](/components/alert) in the page.
- For a decision before an action runs, use an [Alert Dialog](/components/alert-dialog).
- For an error in a form field, show it under the field.

## Examples

### Types

`toast()`, `toast.success()`, `toast.info()`, `toast.warning()` and `toast.error()` set the icon.
Reserve `error` for failures the user should act on.

```tsx
import { toast } from "sonner"
import { Button } from "@zenoxai/ui/components/button"

function ToasterTypes() {
  return (
    <>
      <Button variant="outline" onClick={() => toast("Filter saved")}>
        Default
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.success("Alert assigned to Marina Santos")}
      >
        Success
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.info("Scan queued behind 2 other scans")}
      >
        Info
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.warning("API key expires in 3 days")}
      >
        Warning
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.error("Could not reach the SIEM connector")}
      >
        Error
      </Button>
    </>
  )
}
```

### Status colors

`toast.success()`, `toast.info()`, `toast.warning()` and `toast.error()` take the soft fill,
border and text of the [Alert](/components/alert) of the same tone, and the icon repeats the
type, so the status never rests on color alone. A plain `toast()` stays on the neutral surface.
Set `richColors={false}` on `Toaster` only if a product needs every toast neutral.

```tsx
import { toast } from "sonner"
import { Button } from "@zenoxai/ui/components/button"

function ToasterRichColors() {
  return (
    <>
      <Button
        variant="outline"
        onClick={() =>
          toast.success("Host isolated", {
            description: "ws-finance-07 can reach only the Zenox agent.",
          })
        }
      >
        Success
      </Button>
      <Button
        variant="outline"
        onClick={() =>
          toast.error("Isolation failed", {
            description: "The agent on ws-finance-07 did not respond.",
          })
        }
      >
        Error
      </Button>
    </>
  )
}
```

### With a description

`description` adds a second line with the detail: which asset, how many records.

```tsx
import { toast } from "sonner"
import { Button } from "@zenoxai/ui/components/button"

function ToasterWithDescription() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast.success("Vulnerability scan finished", {
          description: "srv-db-01.prod: 2 critical, 5 high, 14 medium.",
        })
      }
    >
      Finish scan
    </Button>
  )
}
```

### With an action

`action` adds a button to the toast. Use it for "Undo" after a reversible bulk action, instead of
asking for confirmation first.

```tsx
import { toast } from "sonner"
import { Button } from "@zenoxai/ui/components/button"

function ToasterWithAction() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast("12 alerts archived", {
          action: {
            label: "Undo",
            onClick: () => toast("Alerts restored"),
          },
        })
      }
    >
      Archive alerts
    </Button>
  )
}
```

### Promise

`toast.promise()` shows a loading toast while a promise runs and replaces it with the success or
error message when it settles.

```tsx
import { toast } from "sonner"
import { Button } from "@zenoxai/ui/components/button"

function ToasterPromise() {
  function exportCsv() {
    // Stands in for the request that builds the export.
    const request = new Promise<{ rows: number }>((resolve) =>
      setTimeout(() => resolve({ rows: 1284 }), 2000)
    )

    toast.promise(request, {
      loading: "Exporting alerts",
      success: (data) => `Exported ${data.rows} alerts`,
      error: "Export failed",
    })
  }

  return (
    <Button variant="outline" onClick={exportCsv}>
      Export CSV
    </Button>
  )
}
```

## Accessibility

- Toasts are announced by screen readers through a live region and do not take focus.
- A toast closes on its own after a few seconds and pauses while the pointer is over it. Do not
  put the only path to an action in a toast: an "Undo" button must have an equivalent elsewhere,
  such as the archive.
- Alt+T moves focus to the toasts, so keyboard users can reach an action button.

## API reference

`import { ... } from "@zenoxai/ui/components/sonner"`

### Toaster

No props of its own.

