Alert Dialog
Diálogo de confirmação que interrompe o usuário antes de uma ação importante ou irreversível, como excluir um cliente.
'use client';
import { AlertDialog, AlertDialogContent } from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
export default function AlertDialogDemo() {
return (
<AlertDialog>
<Button variant="destructive">Excluir cliente</Button>
<AlertDialogContent
variant="destructive"
title="Excluir cliente?"
description="Mercadinho Bom Preço e todo o histórico de pedidos serão removidos. Essa ação não pode ser desfeita."
confirmLabel="Excluir cliente"
onConfirm={() => console.log('cliente excluído')}
/>
</AlertDialog>
);
}Instalação
npx shadcn@latest add @lenstech/alert-dialogUso
import { AlertDialog, AlertDialogContent } from "@/components/ui/alert-dialog"
import { Button } from "@/components/ui/button"<AlertDialog>
<Button variant="destructive">Excluir cliente</Button>
<AlertDialogContent
variant="destructive"
title="Excluir cliente?"
description="Essa ação não pode ser desfeita."
onConfirm={() => excluirCliente(id)}
/>
</AlertDialog>Com title, description e onConfirm o componente monta cabeçalho, botões de cancelar/confirmar e o
comportamento de fechar sozinho. Para layouts diferentes, veja Composição manual.
Diferenças para o Dialog
O Alert Dialog usa role="alertdialog", não fecha ao clicar fora e não tem o botão "X": o usuário precisa
escolher explicitamente entre cancelar e confirmar. Assim como no Dialog, o primeiro
filho de AlertDialog é o gatilho e o segundo é o conteúdo.
Exemplos
Ação assíncrona
Se onConfirm retornar uma Promise, o botão de confirmar entra em isPending (com spinner), o cancelar fica
desabilitado e o Esc é bloqueado até a Promise resolver. Ao resolver, o diálogo fecha; se ela rejeitar, o
diálogo continua aberto para o usuário tentar de novo.
'use client';
import { useState } from 'react';
import { AlertDialog, AlertDialogContent } from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
const esperar = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
export default function AlertDialogAsync() {
const [cancelado, setCancelado] = useState(false);
return (
<div className="flex flex-col items-center gap-3">
<AlertDialog>
<Button variant="outline" isDisabled={cancelado}>
Cancelar agendamento
</Button>
<AlertDialogContent
variant="destructive"
title="Cancelar agendamento?"
description="A paciente Ana Souza receberá um aviso por WhatsApp e o horário das 14h ficará livre."
confirmLabel="Sim, cancelar"
cancelLabel="Voltar"
onConfirm={async () => {
await esperar(1500); // simula a chamada à API
setCancelado(true);
}}
/>
</AlertDialog>
{cancelado && <p className="text-sm text-muted-foreground">Agendamento cancelado.</p>}
</div>
);
}Confirmação neutra
Sem variant="destructive" o botão de confirmar usa o estilo primário e não há ícone de alerta. O rótulo padrão
passa a ser "Confirmar".
'use client';
import { AlertDialog, AlertDialogContent } from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
export default function AlertDialogDefault() {
return (
<AlertDialog>
<Button>Publicar cardápio</Button>
<AlertDialogContent
title="Publicar novo cardápio?"
description="Os preços atualizados passam a aparecer no site e no link do WhatsApp imediatamente."
confirmLabel="Publicar"
onConfirm={() => console.log('cardápio publicado')}
/>
</AlertDialog>
);
}Composição manual
Sem a prop title, os filhos são renderizados livremente. Use AlertDialogHeader, AlertDialogTitle,
AlertDialogDescription, AlertDialogFooter, AlertDialogCancel e AlertDialogAction — e a função close para
fechar ao confirmar.
'use client';
import { useState } from 'react';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
export default function AlertDialogComposed() {
const [notificar, setNotificar] = useState(true);
return (
<AlertDialog>
<Button variant="outline">Arquivar orçamento</Button>
<AlertDialogContent>
{({ close }) => (
<>
<AlertDialogHeader>
<AlertDialogTitle>Arquivar orçamento #318?</AlertDialogTitle>
<AlertDialogDescription>
Ele sai da lista de pendentes, mas continua disponível em “Arquivados”.
</AlertDialogDescription>
</AlertDialogHeader>
<Checkbox isSelected={notificar} onChange={setNotificar}>
Avisar o cliente por e-mail
</Checkbox>
<AlertDialogFooter>
<AlertDialogCancel>Cancelar</AlertDialogCancel>
<AlertDialogAction
onPress={() => {
console.log('arquivado', { notificar });
close();
}}
>
Arquivar
</AlertDialogAction>
</AlertDialogFooter>
</>
)}
</AlertDialogContent>
</AlertDialog>
);
}Controlado
Use isOpen e onOpenChange no AlertDialog para abrir por código — por exemplo, ao tentar sair de uma tela com
alterações não salvas.
Ficha com alterações não salvas.
'use client';
import { useState } from 'react';
import { AlertDialog, AlertDialogContent } from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
export default function AlertDialogControlled() {
const [open, setOpen] = useState(false);
const [status, setStatus] = useState('Ficha com alterações não salvas.');
return (
<div className="flex flex-col items-center gap-3">
<Button variant="outline" onPress={() => setOpen(true)}>
Sair sem salvar
</Button>
<p className="text-sm text-muted-foreground">{status}</p>
<AlertDialog isOpen={open} onOpenChange={setOpen}>
<AlertDialogContent
title="Descartar alterações?"
description="Você editou a ficha do paciente e ainda não salvou."
confirmLabel="Descartar"
cancelLabel="Continuar editando"
onConfirm={() => setStatus('Alterações descartadas.')}
/>
</AlertDialog>
</div>
);
}Quando usar
- Use antes de ações destrutivas ou difíceis de desfazer: excluir, cancelar agendamento, descartar alterações.
- Use com moderação: se tudo pede confirmação, o usuário passa a clicar sem ler.
- Não use para formulários ou conteúdo livre — use
Dialog. - Não use para avisar que algo deu certo — use
Toast. - Se a ação pode ser desfeita facilmente, prefira executar direto e oferecer "Desfazer" num toast com ação.
API
AlertDialog
Mesmo componente que Dialog (DialogTrigger do React Aria): aceita isOpen,
defaultOpen e onOpenChange.
AlertDialogContent
Aceita as props de DialogContent (exceto showCloseButton), mais:
Prop
Type
Partes para composição
Prop
Type