# Toast stack
> Toast stack where new toasts spring up from below, hover or focus fans the stack out and pauses timers, and a sideways swipe dismisses.
- React: `import { UiToastStack } from "@/components/lumesec/ui-toast-stack"`
- Collection: Interaction (https://elements.lumesec.ai/components/interaction)
- Registry item: https://elements.lumesec.ai/r/ui-toast-stack.json
- Page: https://elements.lumesec.ai/components/interaction/toast-stack



Live preview: https://elements.lumesec.ai/view/ui-toast-stack

Demo source:

```tsx
"use client";

import * as React from "react";

import { UiToastStack, type UiToastStackHandle } from "@/components/lumesec/ui-toast-stack";

export default function UiToastStackDemo() {
  const toasts = React.useRef<UiToastStackHandle>(null);

  // two sample toasts arrive shortly after the demo mounts
  React.useEffect(() => {
    const first = window.setTimeout(() => toasts.current?.show(), 500);
    const second = window.setTimeout(() => toasts.current?.show(), 900);
    return () => {
      window.clearTimeout(first);
      window.clearTimeout(second);
    };
  }, []);

  return <UiToastStack ref={toasts} className="w-full max-w-[660px]" />;
}
```

## Playground

Change a prop and the component re-renders. Props marked remounts set an initial value, so the component starts over.

## Installation

```bash
npx shadcn@latest add @lumesec/ui-toast-stack
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/ui-toast-stack.json
```

## Usage

React:

```tsx
"use client";

import * as React from "react";

import { UiToastStack, type UiToastStackHandle } from "@/components/lumesec/ui-toast-stack";

export function Example() {
  const toasts = React.useRef<UiToastStackHandle>(null);
  return (
    <div className="grid gap-3">
      <UiToastStack ref={toasts} trigger={false} />
      <button
        type="button"
        onClick={() => toasts.current?.show({ title: "Saved", description: "All changes are stored.", tone: "success" })}
      >
        Save
      </button>
    </div>
  );
}
```

## Behaviour

New toasts spring up from below and older ones tuck in behind. Hovering fans the stack out and pauses the timers; swipe a toast sideways to throw it away.

## API reference

### Props

Also accepts every prop of `<div>` (`React.ComponentProps<"div">`), spread onto the root element.

| Prop      | Type                            | Default | Description                                                                           |
| --------- | ------------------------------- | ------- | ------------------------------------------------------------------------------------- |
| `trigger` | `boolean`                       | `true`  | Render the "Show toast" button under the stack, which shows the next built-in sample. |
| `ref`     | `React.Ref<UiToastStackHandle>` | —       | Exposes `show()`.                                                                     |

### Ref

`ref` receives a `UiToastStackHandle` handle with these methods.

| Method                           | Description                                                                                                                                                                |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `show(toast?: ToastInput): void` | Adds a toast `{ title: string; description?: string; tone?: "accent" \| "success" \| "warning" \| "destructive" }`. Without an argument it shows the next built-in sample. |

## Keyboard

| Keys          | Action                                   |
| ------------- | ---------------------------------------- |
| Space / Enter | On a toast's dismiss button, dismiss it. |

## Accessibility

* Toasts are placed in an element with `role="region"`, `aria-label="Notifications"` and `aria-live="polite"`; each toast has `role="status"`.
* Each toast has a native dismiss button labelled "Dismiss". Buttons on toasts hidden at the back of the stack are taken out of the tab order.
* Moving focus into the stack expands it and pauses the timers, as hovering does.
* Swiping is pointer-only; the dismiss button is the keyboard path.
* Reduced motion: toasts appear, fan out, settle and leave without transitions; a swipe still follows the pointer.

## Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--card`, `--muted`, `--border`, `--foreground`, `--muted-foreground`, `--lumesec`, `--lumesec-success`, `--lumesec-warning` and `--destructive`.

## Notes

* Ships with six sample toasts (published, copied, connector added, upload failed, memory updated, files uploaded) that `show()` cycles through when called without an argument.
* Each toast lives 5 s, and timers pause while the stack is expanded or a toast is held. At most five toasts are kept and three are visible; a sixth removes the oldest.
* A swipe of more than 80 px, or a fast flick, throws the toast away. The stack area is 196 px tall and up to 340 px wide.


