# B2B Toast

Floating, transient feedback for B2B page layouts. Toasts slide in from a fixed corner of the viewport, auto-dismiss after a few seconds, and stack vertically. Use for brief confirmations and non-blocking status messages.

> **See also:** [`@xsolla/xui-b2b-notification-panel`](../notification-panel/README.md) for inline (non-floating) feedback that stays in place until dismissed.

## Installation

```bash
yarn add @xsolla/xui-b2b-toast
```

## Quick start

Wrap your app with `ToastProvider` once, then call `useToast()` from anywhere inside.

```tsx
import { ToastProvider, useToast } from "@xsolla/xui-b2b-toast";
import { Button } from "@xsolla/xui-button";

function App() {
  return (
    <ToastProvider position="top-right" limit={3}>
      <Page />
    </ToastProvider>
  );
}

function Page() {
  const toast = useToast();
  return (
    <Button
      onPress={() =>
        toast.success({
          title: "Saved",
          description: "Your changes have been saved.",
          action: <Button onPress={() => undo()}>Undo</Button>,
        })
      }
    >
      Save
    </Button>
  );
}
```

## API

### `<ToastProvider>`

| Prop        | Type             | Default        | Description                                   |
| ----------- | ---------------- | -------------- | --------------------------------------------- |
| `position`  | `ToastPosition`  | `"top-right"`  | Viewport corner to anchor toasts to.          |
| `limit`     | `number`         | `3`            | Max simultaneously visible toasts.            |
| `container` | `HTMLElement`    | `document.body`| Portal target.                                |

`ToastPosition` = `"top-right" \| "top-left" \| "top-center" \| "bottom-right" \| "bottom-left" \| "bottom-center"`

### `useToast()`

```ts
const toast = useToast();
toast.alert(options);    // role=alert, default 9000ms
toast.success(options);  // default 4500ms
toast.warning(options);  // default 6500ms
toast.info(options);     // default 6500ms
toast.show(type, options);
toast.dismiss(id);
toast.dismissAll();
```

`ToastOptions`:

| Field             | Type                  | Description                                              |
| ----------------- | --------------------- | -------------------------------------------------------- |
| `title`           | `string`              | Title (bodyMd accent).                                    |
| `description`     | `string`              | Optional description (bodySm).                           |
| `action`          | `ReactElement`        | Button/IconButton; tone & size are auto-applied.         |
| `showCloseButton` | `boolean`             | Default `true`.                                          |
| `duration`        | `number`              | Auto-dismiss in ms. `0` disables.                        |
| `id`              | `string`              | Stable id; reusing replaces the existing toast.          |
| `onDismiss`       | `() => void`          | Fires when toast is removed (auto, manual, or replaced). |

### `<Toast>`

The visual component, used internally by the provider but exported for advanced cases (custom rendering, snapshot stories, etc.).

```tsx
<Toast
  type="alert"
  title="Project deleted"
  description='Project "Project Name" deleted'
  action={<Button>Undo</Button>}
  onClose={() => {}}
/>
```

## Behavior

- **Auto-dismiss** — success 4.5s, info/warning 6.5s, alert 9s. Pass `duration={0}` to make a toast sticky.
- **Pause on hover/focus** — auto-dismiss timer pauses while the toast is hovered or focused, and resumes on leave/blur.
- **Stacking** — newest toast appears closest to the screen edge. When `limit` is exceeded, the oldest toast is dropped.
- **Accessibility** — `alert` toasts use `role="alert"` / `aria-live="assertive"`; the rest use `role="status"` / `aria-live="polite"`.
