# Confirm button (goodtabs UI)

A two-step button that asks for a second click before it runs an action.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/confirm-button.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/confirm-button`

## Usage

```tsx
import { ConfirmButton } from "@/components/ui/confirm-button"

<ConfirmButton variant="outline" confirmLabel="Delete it?" onConfirm={remove}>
  Delete
</ConfirmButton>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| confirmLabel | `string` | `"Confirm?"` | The label shown after the first click. |
| timeout | `number` | `3000` | How long the confirm label stays before the button reverts, in milliseconds. |
| onConfirm | `() => void` |  | Runs on the second click, within the timeout. |
| variant, size | `Button props` | `"default", "default"` | Every shadcn Button prop except onClick passes through. |

## When to use

- Inline destructive actions in rows and lists where a dialog would be heavy: remove, clear, reset
- Actions that are easy to undo or cheap to redo, but worth a pause
- Dense admin screens where people repeat the action many times

## When not to use

- For actions that cannot be undone and affect other people; use a confirm dialog that explains the outcome
- When the button sits where an accidental double click is likely, such as next to a submit
- For actions that need input, such as typing a name to confirm

## Notes for agents

- It takes a function (onConfirm), so the component rendering it must be a client component
- Both labels sit in the same grid cell, so the button keeps the width of the longer one and nothing shifts
- Armed state is data-armed on the button; an aria-live region announces that a second press confirms
- Escape disarms. For a solid destructive look pass className="bg-destructive text-background", not the soft destructive variant

Docs: https://ui.goodtabs.co/components/confirm-button