useButtonFeedback
Executa uma ação assíncrona passando por carregamento, sucesso e erro, pulando o spinner em requisições rápidas e mantendo o erro na tela enquanto você o lê.
pnpm dlx shadcn@latest add https://hextaui.com/r/use-button-feedback.jsonAdiciona o hook e tudo de que ele depende ao seu projeto.
Copie e cole o código a seguir no seu projeto.
hooks/use-button-feedback.ts Atualize os caminhos de importação para corresponder à configuração do seu projeto.
<Button feedback> executa este fluxo para você quando seu onClick retorna uma promise. Use o hook quando o trabalho começa em outro lugar, como o onSubmit de um formulário, um atalho de teclado ou um blur. Também funciona quando o status pertence a algo que não é um botão.
track() recebe uma promise, ou uma função que retorna uma, e move status por idle, loading, depois success ou error, e de volta a idle. O tempo é o que o faz parecer calmo.
| Etapa | Descrição |
|---|---|
0–150ms | O status permanece idle. Uma requisição que termina nesta janela vai direto para success ou error, sem spinner. |
loading | Exibido a partir de 150ms. Depois de exibido, dura pelo menos 400ms, para nunca piscar. |
success | Mantido por 2 segundos por padrão, depois volta a idle. |
error | Mantido por 4 segundos por padrão. Enquanto o ponteiro está sobre o botão, ou ele tem foco do teclado, o reset espera até saírem, mais 600ms. |
- Chamadas a
track()enquanto uma requisição está em andamento são ignoradas, então um clique duplo ou a tecla Enter segurada nunca envia a requisição duas vezes. - Uma função passada a
track()que lança erro de forma síncrona é tratada como uma promise rejeitada. reset()volta a idle de imediato. O que a requisição abandonada fizer depois é ignorado, assim como qualquer coisa que termine depois da desmontagem do componente.- A retenção do erro só conta hover real do mouse e foco do teclado. O toque não tem hover, e o foco de um clique não é
:focus-visible, então nenhum dos dois mantém o erro.
Formulários
Chame track() em onSubmit e espalhe buttonProps no botão de envio. Remova o @ para ver o erro.
Status sem botão
Leia status para controlar qualquer UI. Esta nota salva quando perde o foco e mostra o resultado ao lado, em uma região role="status" que os leitores de tela anunciam.
resetAfter aceita um número para os dois resultados, ou um objeto para definir cada um. error guarda o último motivo da rejeição, para você mostrá-lo no rótulo, como faz o exemplo de detalhes do erro do Button.
- Dê a cada botão seu próprio hook. Dois botões compartilhando o mesmo
buttonPropsmostram o mesmo status. onStatusChangeeonErrorsempre chamam a função mais recente que você passou, então funções inline funcionam bem.- Use
isPending()para proteger trabalho fora detrack(). Ele lê uma ref, então é preciso mesmo antes da próxima renderização.
| Prop | Tipo | Padrão |
|---|---|---|
resetAfterQuanto tempo success e error permanecem antes de voltar a idle. | number | { success?: number; error?: number } | { success: 2000, error: 4000 } |
onStatusChangeChamado a cada mudança de status. | (status: ButtonStatus) => void | – |
onErrorChamado com o motivo da rejeição. | (error: unknown) => void | – |
| Propriedade | Descrição |
|---|---|
track(action) | Passe uma promise ou uma função que retorne uma. Ignorado enquanto uma requisição está em andamento. |
buttonProps | status mais handlers de ponteiro e foco. Espalhe em <Button>, ou em qualquer coisa que componha esses handlers. |
status | "idle" | "loading" | "success" | "error" |
error | O último motivo de rejeição. |
reset() | Volta a idle agora e ignora a requisição em andamento. |
isPending() | Se há uma requisição em andamento. |
Button por meio da sua prop feedback.