# Confirm Destructive Actions

**MUST** · **ID:** `interactions-confirm-destructive` · **Category:** interactions
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/interactions-confirm-destructive

> MUST: Confirm destructive actions or provide Undo window

Require confirmation or provide Undo with a safe window

Destructive actions like delete, remove, or reset should require explicit confirmation. Show a modal or dialog explaining what will be lost. Alternatively, perform the action but provide an undo option for a reasonable time window (e.g., 5-10 seconds).

## Bad — do not do this

`interactions-confirm-destructive-bad`

```tsx
import { useState } from 'react';
import { Trash2 } from 'lucide-react';

export function ConfirmDestructiveBad() {
  const [items, setItems] = useState(['Document 1', 'Document 2', 'Document 3']);

  const handleDelete = (index: number) => {
    setItems(items.filter((_, i) => i !== index));
  };

  return (
    <div className="w-full max-w-sm">
      <div className="space-y-2">
        {items.map((item, index) => (
          <div key={index} className="flex items-center justify-between p-3 bg-muted rounded-lg">
            <span className="text-sm">{item}</span>
            <button
              onClick={() => handleDelete(index)}
              className="p-1 text-destructive hover:text-destructive/80 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-destructive rounded"
              aria-label="Delete"
            >
              <Trash2 className="w-4 h-4" />
            </button>
          </div>
        ))}
      </div>
      <p className="text-xs text-error mt-4">
        Immediate deletion with no confirmation or undo
      </p>
    </div>
  );
}
```

## Good — do this

`interactions-confirm-destructive-good`

```tsx
import { useState } from 'react';
import { Trash2, Undo } from 'lucide-react';

export function ConfirmDestructiveGood() {
  const [items, setItems] = useState(['Document 1', 'Document 2', 'Document 3']);
  const [deletedItem, setDeletedItem] = useState<{ item: string; index: number } | null>(null);

  const handleDelete = (index: number) => {
    const item = items[index];
    setDeletedItem({ item, index });
    setItems(items.filter((_, i) => i !== index));

    setTimeout(() => {
      setDeletedItem(null);
    }, 5000);
  };

  const handleUndo = () => {
    if (deletedItem) {
      const newItems = [...items];
      newItems.splice(deletedItem.index, 0, deletedItem.item);
      setItems(newItems);
      setDeletedItem(null);
    }
  };

  return (
    <div className="w-full max-w-sm">
      {deletedItem && (
        <div className="mb-3 p-3 bg-primary/10 border border-primary/20 rounded-lg flex items-center justify-between">
          <span className="text-sm text-foreground">Deleted "{deletedItem.item}"</span>
          <button
            onClick={handleUndo}
            className="flex items-center gap-1 text-sm text-primary hover:text-primary/80 font-medium focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring rounded px-2 py-1"
          >
            <Undo className="w-3 h-3" />
            Undo
          </button>
        </div>
      )}
      <div className="space-y-2">
        {items.map((item, index) => (
          <div key={index} className="flex items-center justify-between p-3 bg-muted rounded-lg">
            <span className="text-sm">{item}</span>
            <button
              onClick={() => handleDelete(index)}
              className="p-1 text-destructive hover:text-destructive/80 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-destructive rounded"
              aria-label="Delete"
            >
              <Trash2 className="w-4 h-4" />
            </button>
          </div>
        ))}
      </div>
      <p className="text-xs text-success mt-4">
        Provides undo option for 5 seconds after deletion
      </p>
    </div>
  );
}
```

## References

- [Preventing User Errors](https://www.nngroup.com/articles/slips/)
