HextaUI

useInvalidShake

Fait vibrer un contrôle de formulaire lorsqu’une tentative d’envoi le trouve invalide, et jamais pendant que quelqu’un tape encore.

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

Ajoute le hook et tout ce dont il dépend à votre projet.

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>

Le hook ne fait que définir un attribut data-shake. Le mouvement vient du animate-button-shake du thème, que vous attachez avec data-shake:motion-safe:animate-button-shake. Input, Textarea, Native select et Input group de HextaUI incluent déjà cette classe et appellent le hook. Utilisez-le directement pour vos propres contrôles.

Un tremblement répond à une question : pourquoi mon envoi n'a-t-il pas fonctionné ? Le hook ne fait donc trembler que juste après une tentative d'envoi, et jamais pendant que l'on remplit encore le formulaire.

ÉvénementDescription
Submit attemptUn clic sur un bouton d'envoi, un appui sur Enter dans un champ du formulaire, ou l'événement submit du formulaire.
Invalid within 600msLe contrôle déclenche invalid, ou a aria-invalid="true", data-invalid ou :user-invalid. Cela couvre la validation native, les champs Base UI et les erreurs serveur définies juste après l'envoi.
Shakedata-shake est défini pendant 400ms. Il tremble une fois par tentative, quel que soit le nombre de ces signaux reçus.
  • Dans un InputGroup, c'est tout le groupe qui tremble, pas seulement le contrôle interne.
  • Avec la réduction des animations, rien n'est défini. Dans tous les cas, associez le tremblement à un message d'erreur visible, car le tremblement est un signal, pas le message.
  • Le hook exige que le contrôle appartienne à un <form>. Sans cela, il ne fait rien.
  • Désactivez-le par contrôle avec l'argument enabled, ou avec shake={false} sur les champs de HextaUI.
  • Relancer l'attribut relance l'animation : une seconde tentative échouée fait donc trembler de nouveau même si la première est encore en cours.
  • La validation native donne le focus au premier contrôle invalide à l'envoi. Le tremblement n'ajoute que du mouvement par-dessus et ne déplace jamais le focus.
PropTypePar défaut
refLe contrôle de formulaire à surveiller.
RefObject<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement | null>–
enabledIndique s'il faut trembler.
booleantrue
AttributDescription
data-shakePrésent pendant 400ms après une tentative d'envoi échouée, sur le contrôle ou son InputGroup.

Input, Textarea, NativeSelect et InputGroup.