HextaUI

useInvalidShake

Sacode um controle de formulário quando uma tentativa de envio o encontra inválido, e nunca enquanto alguém ainda está digitando.

Submit without choosing.
"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { useInvalidShake } from "@/hooks/use-invalid-shake"

export function UseInvalidShakeDemo() {
  const ref = React.useRef<HTMLSelectElement>(null)
  const [sent, setSent] = React.useState<string>()
  useInvalidShake(ref)

  return (
    <form
      className="flex w-full max-w-xs flex-col gap-3"
      onSubmit={(event) => {
        event.preventDefault()
        setSent(String(new FormData(event.currentTarget).get("plan")))
      }}
    >
      <label className="flex flex-col gap-2 text-sm font-medium">
        Plan
        <select
          ref={ref}
          name="plan"
          required
          defaultValue=""
          className="h-9 rounded-md bg-muted px-2.5 text-sm font-normal outline-none focus-visible:ring-3 focus-visible:ring-focus-ring focus-visible:outline-hidden data-shake:motion-safe:animate-button-shake pointer-coarse:text-touch [&:user-invalid]:ring-2 [&:user-invalid]:ring-destructive/40"
        >
          <option value="" disabled>
            Choose a plan
          </option>
          <option value="hobby">Hobby</option>
          <option value="pro">Pro</option>
        </select>
      </label>
      <Button type="submit" size="sm">
        Continue
      </Button>
      <output className="text-sm text-muted-foreground">
        {sent ? `plan=${sent}` : "Submit without choosing."}
      </output>
    </form>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/use-invalid-shake.json

Adiciona o hook e tudo de que ele depende ao seu projeto.

import { useInvalidShake } from "@/hooks/use-invalid-shake"
const ref = React.useRef<HTMLSelectElement>(null)
useInvalidShake(ref)

<form>
  <select
    ref={ref}
    required
    className="data-shake:motion-safe:animate-button-shake"
  >
    …
  </select>
  <button type="submit">Continue</button>
</form>

O hook apenas define um atributo data-shake. O movimento vem do animate-button-shake do tema, que você anexa com data-shake:motion-safe:animate-button-shake. Input, Textarea, Native select e Input group do HextaUI já incluem essa classe e chamam o hook. Use-o diretamente nos seus próprios controles.

Um tremor responde a uma pergunta: por que meu envio não funcionou? Por isso o hook só treme logo depois que alguém tenta enviar, e nunca enquanto a pessoa ainda preenche o formulário.

EventoDescrição
Submit attemptClicar em um botão de envio, pressionar Enter em um input do formulário, ou o evento submit do formulário.
Invalid within 600msO controle dispara invalid, ou tem aria-invalid="true", data-invalid ou :user-invalid. Isso cobre a validação nativa, os fields do Base UI e erros do servidor definidos logo após o envio.
Shakedata-shake é definido por 400ms. Treme uma vez por tentativa, não importa quantos desses sinais cheguem.
  • Dentro de um InputGroup, o grupo inteiro treme, não apenas o controle interno.
  • Com movimento reduzido, nada é definido. Combine o tremor com uma mensagem de erro visível de qualquer forma, já que o tremor é uma pista, não a mensagem.
  • O hook precisa que o controle pertença a um <form>. Sem um, ele não faz nada.
  • Desative por controle com o argumento enabled, ou com shake={false} nos inputs do HextaUI.
  • Reiniciar o atributo reinicia a animação, então uma segunda tentativa falha treme de novo mesmo que a primeira ainda esteja rodando.
  • A validação nativa foca o primeiro controle inválido no envio. O tremor apenas acrescenta movimento por cima e nunca move o foco.
PropTipoPadrão
refO controle de formulário a observar.
RefObject<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null>–
enabledSe deve tremer.
booleantrue
AtributoDescrição
data-shakePresente por 400ms depois de uma tentativa de envio falha, no controle ou em seu InputGroup.

Input, Textarea, NativeSelect e InputGroup.