# Undo toast

> A toast after a delete with a button that restores the record from the trash.

- Block: [trash](https://bettersupabase.com/blocks/trash.md)
- Kind: component
- Data: loaded on the server through the block's client
- Page: https://bettersupabase.com/recipes/undo-toast

## Install the block

```bash
npx better-supabase add trash
```

## Web (Next.js)

Add the shadcn components:

```bash
npx shadcn add sonner
```

From `apps/examples/nextjs/src/features/trash/components/undo-toast.tsx` (https://github.com/ScaleDockHQ/better-supabase/blob/main/apps/examples/nextjs/src/features/trash/components/undo-toast.tsx):

```tsx
"use client";

import { useAction } from "better-supabase/react";
import { useExtracted } from "next-intl";
import { toast } from "sonner";

import { useErrorMessage } from "@/lib/use-error-message";

import { restoreTrashItem } from "../trash-actions";

export interface TrashedRecord {
  /** The trash item the delete returned. */
  readonly trashItemId: string;
  readonly name: string;
}

/**
 * Returns `show`, which confirms a delete with a toast whose Undo button
 * restores the record's whole trash batch.
 */
export function useUndoToast() {
  const t = useExtracted("trash");
  const errorMessage = useErrorMessage();

  const restore = useAction(restoreTrashItem, {
    onSuccess: () => {
      toast.success(t("Restored"));
    },
    onError: (error) => {
      toast.error(errorMessage(error));
    },
  });

  return function show({ trashItemId, name }: TrashedRecord) {
    toast(
      <span data-recipe="undo-toast">
        {t("{name} moved to the trash", { name })}
      </span>,
      {
        action: {
          label: t("Undo"),
          onClick: () => {
            void restore.run({ id: trashItemId });
          },
        },
      },
    );
  };
}
```

## Prompt

Paste this into a coding agent to build the recipe in your app.

### Web

```text
Build "Undo toast" in a React web app that uses shadcn/ui components. A toast after a delete with a button that restores the record from the trash.

It uses the better-supabase `trash` block (Trash). It loads its data on the server through the block's client.

Steps:

1. If the app doesn't have the block yet, add the SQL with `npx better-supabase add trash` and apply the migration.
2. Add the shadcn components the recipe uses: `npx shadcn add sonner`.
3. The recipe needs no glue: it calls the block's client on the server.
4. Write the component. Load the data on the server with the block's client, starting from the recipe's snippet (`apps/examples/nextjs/src/features/trash/components/undo-toast.tsx`). Adapt it to the app's existing components, styling and data loading instead of copying it as is.
5. Check the result against the recipe and the block's docs: it typechecks, it reads the same block data, and it handles the loading and empty states the snippet handles.

Read the full code first:

- Recipe: https://bettersupabase.com/recipes/undo-toast.md
- Block docs: https://bettersupabase.com/docs/blocks/trash
```
