Field

Formulario

Agrupa rótulo, controle, descrição e mensagem de erro de um campo de formulário, com a amarração de acessibilidade (htmlFor, aria-describedby, aria-invalid) automática.

Carregando

Instalação

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

npm i @trdr/ui

import { Field } from "@trdr/ui/field"

Uso

import { Field, FieldControl, FieldDescription, FieldError, FieldGroup, FieldLabel } from "@trdr/ui/field"

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

Props

FieldPropsestende React.HTMLAttributes<HTMLDivElement>
PropTipoDescrição
invalid?booleanEstado de invalidacao: liga `aria-invalid` no controle e habilita a `FieldError`.
disabled?booleanEstado desabilitado, refletido no `FieldLabel` (o `Label` nao inspeciona o controle sozinho).
id?stringid do controle. Quando omitido, gera um id estavel via `useId`.
FieldLabelPropsestende LabelProps
FieldControlPropsestende React.HTMLAttributes<HTMLElement>
FieldDescriptionPropsestende React.HTMLAttributes<HTMLParagraphElement>
FieldErrorPropsestende React.HTMLAttributes<HTMLParagraphElement>
FieldGroupPropsestende React.HTMLAttributes<HTMLDivElement>
FieldSetPropsestende React.FieldsetHTMLAttributes<HTMLFieldSetElement>
FieldLegendPropsestende React.HTMLAttributes<HTMLLegendElement>

Field

Agrupa rótulo, controle, descrição e mensagem de erro de um campo de formulário. É o componente que existe para que formulário acessível seja o caminho fácil, não o difícil: quem usa Field não precisa lembrar de gerar um id, escrever htmlFor à mão, montar aria-describedby nem ligar aria-invalid no controle certo.

Quando usar

  • Sempre que um campo (input, textarea, ou qualquer controle nativo) precisar de rótulo, ajuda ou mensagem de erro no seu formulário. Field substitui o padrão manual <div className="flex flex-col gap-xs"><Label/><Input/></div> que os componentes label e input já documentam como composição básica.
  • Para agrupar vários campos relacionados sob um título semântico, use FieldSet + FieldLegend + FieldGroup por cima de vários Field.
  • Como base de composição de outro componente: o form (fora de escopo aqui) usa exatamente estas peças para ligar com o react-hook-form, em vez de duplicar a amarração de acessibilidade.

Quando não usar

  • Para um controle isolado sem rótulo visível (ex. busca compacta com ícone): use aria-label direto no controle, sem Field.
  • Como substituto do input/textarea/label: Field não redesenha esses componentes, só os amarra. A cor de borda de validação (tone) continua sendo escolhida no próprio Input/ Textarea; Field cuida só da semântica (aria-invalid), não do estilo visual.

Anatomia

<FieldSet>                              <fieldset>, semântica de grupo, sem chrome do navegador
  <FieldLegend>                         <legend>, título do grupo
  <FieldGroup>                          agrupa vários Field com o espaçamento padrão
    <Field>                             <div>, provedor do Context de amarração
      <FieldLabel>                      <label> (usa o componente Label por baixo)
      <FieldControl>                    Slot: repassa id/aria-describedby/aria-invalid ao filho
        <Input> ou <Textarea>
      <FieldDescription>                <p>, texto de ajuda, opcional
      <FieldError>                      <p role="alert">, só quando invalid e há mensagem

Props

  • Field: invalid (liga aria-invalid no controle e habilita FieldError), disabled (reflete no FieldLabel), id (gera um automaticamente via useId quando omitido).
  • FieldLabel: todas as props de Label (required, disabled), mais htmlFor opcional para sobrescrever o id gerado pelo Field.
  • FieldControl: envolve um único filho (o controle real) via Slot, no mesmo mecanismo asChild do Button.

Acessibilidade

  • FieldLabel recebe htmlFor automaticamente do Field pai, apontando para o id do controle dentro do FieldControl mais próximo. Um htmlFor explícito sempre pode sobrescrever.
  • FieldDescription e FieldError se registram no Field quando montam. O aria-describedby do controle só referencia os ids que realmente existem no DOM: se você não usar FieldDescription, o controle não aponta para um id inexistente.
  • FieldError só renderiza (e só entra no aria-describedby) quando Field está invalid e há conteúdo. Não é um slot de mensagem genérica: para uma dica sempre visível, use FieldDescription.
  • aria-invalid no controle real vem do Field, e sempre pode ser sobrescrito por um valor explícito que o consumidor escrever diretamente no controle (o className/prop do filho sempre vence, no mesmo espírito do cn()).
  • FieldSet/FieldLegend usam <fieldset>/<legend> nativos: o nome acessível do grupo (role group) vem da legenda, sem precisar de aria-label manual.

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="field"][data-slot="field-control"][data-slot="field-description"][data-slot="field-error"][data-slot="field-group"][data-slot="field-label"][data-slot="field-legend"][data-slot="field-set"]
5 tokens usados
text-b4text-content-errortext-content-secondarytext-content-tertiarytext-l3