# At most one toast/notification library

- **Pattern:** `ab-000230` (`ai-slop-code-drift.tooling-stack-drift.dual-toast-library`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000230
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000230)

## Why it matters

Two toast libraries produce two stacking contexts, two animation timings, and two position anchors. A success toast from sonner might render top-right while an error toast from react-hot-toast renders bottom-center, making notifications feel accidental rather than intentional. Users lose trust in the feedback system, and accessibility is also inconsistent: one library might set `role="status"` while the other uses `role="alert"`, changing how screen readers announce messages.

## Severity rationale

Low because toast drift is a UX polish issue, not a correctness or security concern.

## Remediation

Pick one and migrate every call. Inventory usage with `grep -rl "react-hot-toast" src/`, rewrite each call to the survivor's API (both have roughly equivalent `toast.success`/`toast.error` shapes), then remove the loser:

```bash
npm uninstall react-hot-toast
```

Centralize toast configuration in `src/components/providers/toast-provider.tsx` so position, duration, and theming live in one file and future contributors can't accidentally reintroduce a second library.

## Detection

- **ID:** `dual-toast-library`
- **Severity:** `low`
- **What to look for:** Apply the three-condition rule against this exact toast/notification allowlist: `react-hot-toast`, `react-toastify`, `sonner`, `notistack`, `react-notifications`, `@radix-ui/react-toast`. EXCLUDE if the project uses a component library that ships its own toast (Material UI's `Snackbar`, Chakra's `useToast`, Mantine's `notifications`) — those are part of the component library and don't count separately. Count all REMAINING libraries that meet all three conditions (at least 1 non-escape-hatch importing file).
- **Pass criteria:** 0 or 1 toast libraries from the allowlist actively used. Report even on pass: "Canonical toast library: [name] ([N] importing files)."
- **Fail criteria:** 2 or more toast libraries from the allowlist meet all three conditions (at least 1 non-escape-hatch importing file).
- **Skip (N/A) when:** 0 toast libraries from the allowlist appear in `RUNTIME_DEPS`.
- **Detail on fail:** `"2 active toast libraries: 'react-hot-toast' (5 files) AND 'sonner' (3 files). Pick one for consistent notification UX."`
- **Remediation:** Mixed toast libraries means inconsistent toast positioning, animation, styling. Pick one and migrate:

  ```bash
  grep -rl "react-hot-toast" src/
  # Convert to sonner (or vice versa)
  npm uninstall react-hot-toast
  ```

---

Taxons: dependency-coherence

HTML version: https://auditbuffet.com/patterns/ab-000230
