Form

Formulario

Ponte entre o react-hook-form e o Field: liga cada campo ao estado do formulário mantendo a amarração de acessibilidade automática.

Carregando

Instalação

Recebe correções por update de versão. O caminho recomendado.

npm i @trdr/ui

import { Form } from "@trdr/ui/form"

Uso

import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel } from "@trdr/ui/form"

export function Exemplo() {
  return <Form />
}

Props

FormItemPropsestende Omit<FieldProps, "id" | "invalid">
FormLabelPropsestende FieldLabelProps
FormControlPropsestende FieldControlProps
FormDescriptionPropsestende FieldDescriptionProps
FormMessagePropsestende FieldErrorProps

Form

A ponte entre o react-hook-form e o Field. Liga cada campo ao estado do formulário (valor, validação, erro) sem duplicar a amarração de acessibilidade que o Field já resolve: FormItem renderiza um Field por baixo, e FormLabel/FormControl/FormDescription/FormMessage são FieldLabel/FieldControl/FieldDescription/FieldError com uma camada fina de tradução do estado do react-hook-form.

Quando usar

  • Qualquer formulário com validação: boleta de ordem, cadastro, preferências. O par natural é react-hook-form (estado e validação) + zod (schema) + @hookform/resolvers (a ponte entre os dois), as três únicas dependências além da base que este componente pode usar.
  • Quando o formulário precisa mostrar erro por campo, desabilitar o botão de envio durante validação, ou reagir a mudança de valor de um campo para outro.

Quando não usar

  • Formulário de um campo só, sem validação (ex. busca): um Field isolado (ou só Input com aria-label) já resolve, sem a sobrecarga do react-hook-form.
  • Como camada de estilo: Form não estiliza nada por conta própria, ele só liga estado a acessibilidade. O visual continua sendo do Field/Input/Button por baixo.

Anatomia

<Form {...form}>                        FormProvider do react-hook-form
  <form onSubmit={form.handleSubmit(...)}>
    <FormField control={form.control} name="ativo" render={({ field }) => (
      <FormItem>                        Field por baixo: gera id, computa aria-describedby/invalid
        <FormLabel>                     FieldLabel + cor de erro quando invalido
        <FormControl>                   FieldControl (Slot): id/aria-* no <Input {...field}/>
          <Input {...field} />
        <FormDescription>              FieldDescription
        <FormMessage />                 FieldError, com a mensagem do zod quando ha erro
      </FormItem>
    )} />
  </form>
</Form>

O hook useFormField

Usado internamente por FormLabel/FormControl/FormDescription/FormMessage, e também exportado para quem precisar montar uma parte customizada da UI do formulário sem perder a amarração: devolve { id, name, formItemId, formDescriptionId, formMessageId, error, ...resto do fieldState }. Só funciona dentro do par <FormField> (dá o nome do campo) + <FormItem> (dá o id): usado fora de um dos dois, lança um erro explicando qual está faltando.

Acessibilidade

  • Toda a amarração (htmlFor, aria-describedby, aria-invalid) é a mesma do Field: Form não reimplementa nada disso, só alimenta o invalid do Field a partir do fieldState.error do react-hook-form.
  • FormMessage mostra a mensagem de validação do zod automaticamente (error.message), com role="alert" herdado do FieldError. children funciona como texto de reforço quando o erro existe mas não tem message (caso raro de erro definido manualmente via form.setError).
  • FormLabel ganha data-error e a cor text-content-error quando o campo está inválido, reforçando visualmente o que o leitor de tela já anuncia por aria-invalid.

Slots e tokens

Todo elemento renderizado carrega um data-slot para estilizar partes internas sem depender de classe da biblioteca. Os tokens listados são extraídos do código fonte.

[data-slot="form-control"][data-slot="form-description"][data-slot="form-item"][data-slot="form-label"][data-slot="form-message"]
1 tokens usados
text-content-error