Toast
Notificação passageira que confirma uma ação ou avisa sobre algo sem interromper o que o usuário está fazendo.
'use client';
import { Button } from '@/components/ui/button';
import { Toaster, toast } from '@/components/ui/toast';
export default function ToastDemo() {
return (
<>
<Button
variant="outline"
onPress={() =>
toast.success('Orçamento enviado', {
description: 'O cliente receberá o PDF por e-mail em instantes.',
})
}
>
Enviar orçamento
</Button>
{/* No seu app, o <Toaster /> fica uma única vez no layout raiz. */}
<Toaster />
</>
);
}Instalação
npx shadcn@latest add @lenstech/toastUso
A API é inspirada no sonner: monte o <Toaster /> uma única vez e dispare
toasts de qualquer lugar com toast().
Adicione o <Toaster /> ao layout raiz do app:
import { Toaster } from "@/components/ui/toast"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="pt-BR">
<body>
{children}
<Toaster />
</body>
</html>
)
}Chame toast onde precisar — em handlers, após uma requisição etc.:
import { toast } from "@/components/ui/toast"
toast.success("Orçamento enviado", {
description: "O cliente receberá o PDF por e-mail.",
})API UNSTABLE_ do React Aria
O Toast é construído sobre UNSTABLE_ToastRegion e UNSTABLE_Toast do React Aria. O prefixo indica que a API
do React Aria ainda pode mudar, mas ela já implementa região acessível, anúncio para leitores de tela, navegação
por F6 e pausa do tempo no hover/foco. Como o seu código só usa toast() e <Toaster />, uma eventual mudança
fica restrita ao arquivo do componente.
Um Toaster só
Todos os toasts usam uma fila global. Se mais de um <Toaster /> for montado, apenas o primeiro é exibido (os
exemplos desta página montam o seu próprio só para a prévia funcionar). Por isso a prop position vale apenas
para o <Toaster /> do layout.
Exemplos
Variantes
toast(), toast.success(), toast.error(), toast.warning() e toast.info(). Cada variante tem ícone e cor de
borda próprios.
'use client';
import { Button } from '@/components/ui/button';
import { Toaster, toast } from '@/components/ui/toast';
export default function ToastVariants() {
return (
<div className="flex flex-wrap items-center justify-center gap-3">
<Button variant="outline" onPress={() => toast('Rascunho salvo')}>
Padrão
</Button>
<Button variant="outline" onPress={() => toast.success('Pagamento confirmado')}>
Sucesso
</Button>
<Button variant="outline" onPress={() => toast.error('Não foi possível salvar o cadastro')}>
Erro
</Button>
<Button variant="outline" onPress={() => toast.warning('Seu plano vence em 3 dias')}>
Aviso
</Button>
<Button variant="outline" onPress={() => toast.info('Nova versão do sistema disponível')}>
Informação
</Button>
<Toaster />
</div>
);
}Com ação
Passe action para oferecer, por exemplo, "Desfazer". Toasts com ação não somem sozinhos, a menos que você
informe timeout.
Pedidos arquivados: 0
'use client';
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Toaster, toast } from '@/components/ui/toast';
export default function ToastAction() {
const [arquivados, setArquivados] = useState(0);
return (
<div className="flex flex-col items-center gap-3">
<Button
variant="outline"
onPress={() => {
setArquivados((n) => n + 1);
toast('Pedido #1042 arquivado', {
action: { label: 'Desfazer', onPress: () => setArquivados((n) => n - 1) },
timeout: 6000,
});
}}
>
Arquivar pedido
</Button>
<p className="text-sm text-muted-foreground">Pedidos arquivados: {arquivados}</p>
<Toaster />
</div>
);
}Ação assíncrona
toast() retorna um id. Use timeout: 0 para um aviso que fica na tela e toast.dismiss(id) para fechá-lo
quando a requisição terminar.
'use client';
import { useRef, useState } from 'react';
import { Button } from '@/components/ui/button';
import { Toaster, toast } from '@/components/ui/toast';
const esperar = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
export default function ToastAsync() {
const [pending, setPending] = useState(false);
const tentativas = useRef(0);
async function salvar() {
setPending(true);
const id = toast('Salvando cadastro…', { timeout: 0 });
await esperar(1500); // simula a chamada à API
toast.dismiss(id);
setPending(false);
// Para demonstrar, a 1ª tentativa falha e a 2ª dá certo.
tentativas.current += 1;
if (tentativas.current % 2 === 1) {
toast.error('Não foi possível salvar', {
description: 'Verifique sua conexão e tente de novo.',
action: { label: 'Tentar novamente', onPress: salvar },
});
} else {
toast.success('Cadastro salvo');
}
}
return (
<>
<Button isPending={pending} onPress={salvar}>
Salvar cadastro
</Button>
<Toaster />
</>
);
}Quando usar
- Use para confirmar que algo aconteceu ("Cadastro salvo") ou avisar sobre falhas recuperáveis.
- Não use para informação que o usuário precisa ler com calma ou que deve continuar visível — use
Alert. - Não use para pedir uma decisão — use
Alert Dialog. - Não use para erros de validação de campos: mostre a mensagem junto ao campo.
API
toast
Prop
Type
ToastOptions
Prop
Type
Toaster
Região onde os toasts aparecem, baseada no ToastRegion do React Aria.
Prop
Type