KDS
Forms

Label

Rótulo acessível para controles de formulário — par obrigatório de Input, Select, Checkbox.

Overview

Label é o LabelPrimitive.Root do Radix com estilo do KDS. Ele faz três coisas que um <label> HTML solto não faz com a mesma robustez:

  1. Vincula corretamente ao controle via htmlFor + id, ou ao envolver o controle inline.
  2. Captura cliques e dispara o foco/seleção do controle vinculado, mesmo quando há children intermediários.
  3. Dim automaticamente quando o controle vinculado está disabled, via seletores peer-disabled e group-data-[disabled=true].

Em formulários, Label é obrigatório — ele é o que torna o campo acessível para leitores de tela, navegação por teclado e ferramentas de preenchimento automático.

Preview
Label canônico vinculado a um Input.

Anatomy

<Label htmlFor="control-id">
  Texto do label
  ├─ Asterisco se obrigatório (com aria-label)
  └─ Helper inline opcional (com peer ou children)
</Label>
<Input id="control-id" />

A id do Input deve bater com o htmlFor do Label. react-hook-form

  • FormItem resolvem isso para você — geram um id único via React.useId() e propagam.

Usage

import { Label } from "@kalvner/kds/forms/label";
import { Input } from "@kalvner/kds/forms/input";

export function NameField() {
  return (
    <div className="grid gap-2">
      <Label htmlFor="name">Nome</Label>
      <Input id="name" />
    </div>
  );
}
Default
Label + Input — o par mínimo.

Props

PropTipoDefaultDescrição
htmlForstringID do controle vinculado.
classNamestringClasses Tailwind extras.
...restReact.ComponentProps<typeof LabelPrimitive.Root>Tudo do Radix Label.Root.

States

Required
Asterisco vermelho — anuncie como obrigatório.
Disabled
Dim automático via peer-disabled.
With helper text
Helper abaixo, em muted-foreground.
Usaremos para confirmar a conta.
Inline (Checkbox)
Label inline ao lado do controle.

Composition

Canonical form row
Label + Input + helper — a unidade mínima de qualquer form.
Como aparece no documento de identificação.

When to use

  • Sempre que houver um Input, Textarea, Select, Checkbox, Switch ou Radio. Não há exceção razoável.
  • Para agrupar visualmente um label de uma legenda de fieldset (<fieldset><legend>...) em grupos de controles relacionados.

When not to use

  • Para títulos de seções dentro do formulário — use <h2> / <h3>, não Label.
  • Para placeholder-only "labels" — sem Label visível, leitores de tela perdem contexto e o usuário esquece o campo ao começar a digitar.
  • Para texto descritivo entre Label e Input — esse é o FormDescription, não outro Label.

Best practices

  • Label sempre acima do controle no web. Floating labels (label que vira placeholder quando vazio) podem ser estéticos mas reduzem affordance — um label estático ainda funciona melhor para a maioria.
  • Asterisco com aria-label="obrigatório". Sem o aria-label, o leitor de tela soletra "asterisco". Marque o asterisco como decorativo e atribua o significado correto.
  • Não duplique a label como placeholder. Placeholder é um exemplo ou hint de formato (voce@exemplo.com), não a repetição do label.
  • Cliques na label devem focar o controle. Não envolva texto arbitrário no Label esperando que o usuário descubra que ele é clicável — só o que é semanticamente "o label".

Accessibility

ConcernComportamento
Roles<label> HTML nativo via Radix. Anuncia o controle vinculado.
VinculaçãohtmlFor + id (preferido) ou wrap do controle como child.
Click targetClicar no Label foca o controle. Para Checkbox/Radio, marca/desmarca.
DisabledDim automático via peer-disabled quando o controle vinculado está disabled.
RequiredAsterisco precisa de aria-label="obrigatório". Combine com required no Input.

On this page