# Toaster (React Native)

> Brief messages that stack, auto-dismiss, pause on touch and swipe away. Fire them with toast() from anywhere.

GramproKit for React Native · Overlays · Beta · Source: https://kit.gramproindia.com/native/docs/toaster

> **Beta:** React Native support is in beta. APIs may change or break between prereleases (npm tag `native`).

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/toaster). The example's source:

```tsx
import { useState } from "react";
import { Text } from "react-native";
import { Button } from "@/component-lib/button";
import { useKitTheme } from "@/component-lib/shared/native";
import { toast, Toaster, type ToastPosition } from "@/component-lib/toaster";
import { Row, Section } from "./layout"; // Section and Row: page layout for the demo

const wait = (ms: number, fail = false) =>
  new Promise<string>((resolve, reject) => setTimeout(() => (fail ? reject(new Error("Timed out")) : resolve("42 rows")), ms));

export function ToasterDemo() {
  const { tokens } = useKitTheme();
  const [position, setPosition] = useState<ToastPosition>("top-center");

  return (
    <>
      {/* Normally mounted once at the app root; here so the demo stands alone. */}
      <Toaster position={position} />

      <Section title="toast · types">
        <Row>
          <Button variant="outline" onPress={() => toast("Draft saved")}>
            Default
          </Button>
          <Button variant="outline" onPress={() => toast.success("Payment received", { description: "₹12,500 from Ward 4" })}>
            Success
          </Button>
          <Button variant="outline" onPress={() => toast.error("Upload failed", { description: "Check your connection." })}>
            Error
          </Button>
        </Row>
        <Row>
          <Button variant="outline" onPress={() => toast.warning("Storage almost full")}>
            Warning
          </Button>
          <Button variant="outline" onPress={() => toast.info("New version available")}>
            Info
          </Button>
          <Button
            variant="outline"
            onPress={() => {
              const id = toast.loading("Syncing…");
              setTimeout(() => toast.update(id, { type: "success", title: "Synced", duration: 3000 }), 1500);
            }}
          >
            Loading → done
          </Button>
        </Row>
      </Section>

      <Section title="toast · actions and promise">
        <Row>
          <Button
            variant="secondary"
            onPress={() =>
              toast("Invoice deleted", {
                action: { label: "Undo", onClick: () => toast.success("Restored") },
                cancel: { label: "Dismiss", onClick: () => undefined },
                duration: 8000,
              })
            }
          >
            With undo
          </Button>
          <Button
            variant="secondary"
            onPress={() =>
              void toast
                .promise(wait(1500), {
                  loading: "Importing…",
                  success: (rows) => `Imported ${rows}`,
                  error: (e) => `Import failed: ${(e as Error).message}`,
                })
                .catch(() => undefined)
            }
          >
            Promise
          </Button>
          <Button
            variant="secondary"
            onPress={() =>
              void toast
                .promise(wait(1200, true), { loading: "Exporting…", error: "Export failed" })
                .catch(() => undefined)
            }
          >
            Promise fails
          </Button>
        </Row>
        <Button variant="ghost" onPress={() => toast.dismiss()}>
          Dismiss all
        </Button>
      </Section>

      <Section title="Toaster · position">
        <Row>
          {(["top-center", "bottom-center", "top-right", "bottom-left"] as const).map((p) => (
            <Button key={p} size="sm" variant={p === position ? "primary" : "outline"} onPress={() => setPosition(p)}>
              {p}
            </Button>
          ))}
        </Row>
        <Text style={{ color: tokens.muted }}>Swipe a toast sideways to dismiss it; hold it to pause its timer.</Text>
      </Section>
    </>
  );
}
```

## Install

```bash
npx @grampro/kit@native add Toaster
```

## Usage

```tsx
import { Toaster, toast } from "@/component-lib/toaster";

// Once, inside KitProvider:
<Toaster />

// Anywhere:
toast.success("Invoice sent");
```

## Props

### ToasterProps

| Prop | Type | Description |
|---|---|---|
| `position` | `ToastPosition` | Default `"top-center"` (the web defaults to `top-right`; a phone has no corner to spare). |
| `limit` | `number` | Open toasts on screen at once; the rest wait their turn. Default 3. |
| `duration` | `number` | Default auto-close delay in milliseconds. Default 5000. |
| `closeButton` | `boolean` | Show a close button on dismissible toasts. Default true. |
| `icons` | `Partial<Record<ToastType, ReactNode>>` | Replace the icon per type; `null` hides it. |
| `store` | `ToastStore` | A store from `createToastStore()`. Defaults to the one behind `toast()`. |
| `style` | `StyleProp<ViewStyle>` | The region holding the toasts. |
| `styles` | `ToasterStyles` |   |
| `localeText` | `Partial<ToasterLocaleText>` |   |

## Native and web

- Defaults to `top-center` on native and keeps clear of the notch and gesture bar.
- Known gap: a toast fired from inside an open Modal or Dialog shows once it closes.
- Web version: [Toaster on the web](https://kit.gramproindia.com/toaster).
