Toast

Pronto

Feedback efêmero após uma ação. Aparece, comunica, desaparece. Suporta variantes (success, error, info), action (Desfazer) e empilhamento.

Usar quando

Confirmação de ação não-bloqueante (item criado, salvo, excluído). Erro recuperável (não crítico).

Não usar quando

Erro crítico que precisa atenção (use modal). Mensagem permanente (use banner). Validação de form (use erro inline).

Variantes

3 tipos: success, error, info. Cor é o sinal — sempre acompanhada de ícone.

Área criada com sucesso.
Não foi possível salvar. Tente novamente.
Sua sessão expira em 5 minutos.
Variantes estáticas (sem animação)

Com action (Undo)

Para ações destrutivas reversíveis. Auto-dismiss desabilitado enquanto action existe.

Área excluída.

Demo interativa

Clique para disparar. Veja a animação real (slide in, auto-dismiss em 4s, slide out).

Empilhamento

Múltiplos toasts empilham bottom-up com offset 8px.

Área 'Direito Civil' criada.
3 outras áreas pendentes.
Falha ao sincronizar com 1 servidor.

Microinterações

MicrointeraçãoDisparada porComportamentoTiming
Slide inshowtranslateY(20px)→0 + opacity 0→1250ms cubic-bezier(0.32,0.72,0,1)
Auto-dismiss countdownshowBarra inferior reduz de 100% a 0% em 4s4000ms linear
Hover pausedmouseenterPausa o auto-dismiss enquanto mouse está em cimainstant
Slide outdismiss (auto ou manual)opacity 1→0 + scale 1→0.95200ms cubic-bezier(0.4,0,1,1)
Action clickclique no botão DesfazerToast desaparece imediatamente, action.onClick chamada150ms (sem delay)
Stack reflownovo toast quando já há outrosToasts existentes deslizam 8px para cima250ms ease
Swipe to dismiss (mobile)touchmove horizontal > 80pxToast segue o dedo, opacity reduz, dismiss ao soltarfollows finger

Acessibilidade

Acessibilidade — checklist

Teclado
EscFecha o toast atual (top da pilha)
TabMove foco para o action (se houver)
EnterAciona o action (se em foco)
ARIA esperado
  • role="status" // para success/info (assertive=false)
  • role="alert" // para error (interrompe screen reader)
  • aria-live="polite" // para success/info
  • aria-live="assertive" // para error
  • aria-atomic="true" // garante leitura completa
Notas
  • Toast NUNCA é o único feedback de sucesso de operação crítica — combine com mudança visual no contexto.
  • Auto-dismiss não pode ser <4s (acessibilidade WCAG 2.2.1).
  • Erro NUNCA usa auto-dismiss curto — dá pelo menos 8s ou requer dismiss manual.
  • Em mobile, swipe-to-dismiss horizontal é padrão iOS/Android.

Código

'use client';
import { useEffect, useState } from 'react';
import { CheckCircle2 } from 'lucide-react';
import { T, TYPE, SP, RADIUS, MOTION } from '@/lib/tokens';

interface ToastProps {
  variant: 'success' | 'error' | 'info';
  message: string;
  action?: { label: string; onClick: () => void };
  duration?: number; // ms, default 4000 (8000 para error)
  onDismiss: () => void;
}

export function Toast({ variant, message, action, duration, onDismiss }: ToastProps) {
  const dur = duration ?? (variant === 'error' ? 8000 : 4000);
  const [paused, setPaused] = useState(false);

  useEffect(() => {
    if (action || paused) return; // não auto-dismiss se houver action ou hover
    const t = setTimeout(onDismiss, dur);
    return () => clearTimeout(t);
  }, [paused, action, dur, onDismiss]);

  return (
    <div
      role={variant === 'error' ? 'alert' : 'status'}
      aria-live={variant === 'error' ? 'assertive' : 'polite'}
      onMouseEnter={() => setPaused(true)}
      onMouseLeave={() => setPaused(false)}
      style={{
        background: T.surface,
        border: `1px solid ${T.border}`,
        borderRadius: RADIUS.md,
        boxShadow: T.shadowLg,
        padding: `${SP[3]}px ${SP[4]}px`,
        // ... resto dos estilos
      }}
    >
      {/* ícone + mensagem + action + close */}
    </div>
  );
}

Regras

Faça

  • Mensagem em 1 frase curta (≤80 caracteres). Diga o que aconteceu.
  • Success: 4s de auto-dismiss. Error: 8s ou manual. Info: 4s.
  • Use action (Desfazer) em ações destrutivas reversíveis (excluir).
  • Pausa auto-dismiss em hover/focus.
  • Stack bottom-right com offset 8px entre toasts.
  • Use role="alert" para errors (interrompe screen reader).

Não faça

  • Não use toast para erro crítico (use modal).
  • Não use toast como única confirmação de ação importante.
  • Não passe mensagem em parágrafo — toast é flash, não aviso.
  • Não use cor sem ícone (a11y).
  • Não exiba mais que 3 toasts simultâneos (corte mais antigos).
  • Não desabilite o botão de fechar (X) — usuário sempre pode dismiss.

Tokens usados

TokenValorPapel
T.surface#FFFFFFbackground do card
T.border#E3DFD2borda fina
T.shadowLg0 16px 40px ...sombra de elevação
T.verde#2F6B3Cícone success
T.carmim#A32E2Eícone error
T.selo#2B5A8Aícone info
RADIUS.md12borderRadius
TYPE.base13fontSize message
MOTION.base250msslide in