# Toast

Where toasts appear: bottom right, newest at the bottom. Polite for successes, assertive for errors. Errors stay until dismissed, because a failure that vanishes on its own is easy to miss. Up to four show; past that the oldest toast that isn't an error goes, never a failure, so errors can stack beyond four, and the stack scrolls once it reaches the top of the screen. `offset` (or the `--cd-toast-offset` token) lifts it clear of something fixed at the bottom, such as a chat composer, so a toast never covers Send. If the focused control is under the stack anyway, the stack moves to the top. Screen readers hear each toast through two live regions that are on the page from the start, since a region added together with its text often isn't announced.

- Registry name: `toast` (`@candor/toast`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/toast

## Install

```bash
npx candor-ui add toast
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/toast`.
It brings in: locale, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { Button } from "@/components/ui/button"
import { toast, Toaster } from "@/components/toast"

export default function Example() {
  return (
    <>
      {/* Mount one Toaster near the root of your app; call toast() from anywhere. */}
      <Toaster />
      <div className="flex flex-wrap gap-2">
        <Button
          variant="outline"
          onClick={() =>
            toast({
              tone: "success",
              title: "Migration applied on Staging",
              detail: "0042_add_region ran in 1.8s.",
              action: { label: "Open thread", onClick: () => {} },
            })
          }
        >
          Show a success
        </Button>
        <Button
          variant="outline"
          onClick={() => toast({ tone: "error", title: "The backfill stopped", detail: "The connection to Staging timed out after 40,000 rows." })}
        >
          Show an error
        </Button>
      </div>
    </>
  )
}
```

## <Toaster>

Props:

- `offset?: number | string | undefined`: Space to keep clear below the toasts, such as a composer's height: a number in px or a CSS length.
- `className?: string | undefined`

## Functions

### dismissToast

```ts
dismissToast(id: number)
```

### capToasts

```ts
capToasts(list: T[], max = 4)
```

At most four on screen, but never by dropping a failure: the oldest toast that isn't an error goes first, and the newest always shows. Errors beyond four stay, since each one waits for someone to read it and dismiss it.

### toast

```ts
toast(input: ToastInput)
```

Show a toast. Returns its id. A run finishing in the background is the main use.

## Strings (`toast`)

The fixed words, English by default. Override any of them under `toast` in `<LocaleProvider strings={{ toast: { … } }}>`; the table is exported as `toastStrings`.

- `announcement`: {title}. {detail}
- `dismiss`: Dismiss

## Types

### ToastInput

```ts
{ title: string detail?: string | undefined tone?: "success" | "error" | "info" | undefined action?: { label: string; onClick: () => void } | undefined /** ms; 0 keeps it until dismissed. Errors default to staying. */ duration?: number | undefined }
```

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
