PRIMITIVES

FormField

Accessible wrapper that wires a label, description, and error message to a single input child via aria-describedby and aria-invalid. Ships zero opinions about layout — pair it with Box for stacks.

Import

import { FormField, Input } from 'damo-ui'

Label + description

We'll never share it.
1<FormField label="Email" description="We'll never share it.">
2  <Input type="email" />
3</FormField>

Error state

Pass an error string to surface a validation message. The wrapper sets aria-invalid on the child and links the error to aria-describedby.

Username is already taken.
1<FormField label="Username" error="Username is already taken.">
2  <Input defaultValue="damo" />
3</FormField>

With Textarea

Markdown is supported.
1<FormField label="Notes" description="Markdown is supported.">
2  <Textarea rows={4} />
3</FormField>

Props

FormField props
PropTypeDefaultDescription
label*ReactNodeVisible label rendered as a <label> and wired to the child via htmlFor.
descriptionReactNodeOptional helper text. The id is added to the child via aria-describedby.
errorReactNodeOptional validation message. When present, it is added to aria-describedby and the child also receives aria-invalid=true.
idstringOverride the auto-generated id. Useful when you need to reference the field from outside the form.
children*ReactElementExactly one child element. The wrapper clones it and injects id, aria-describedby, and aria-invalid.
labelClassNamestringCustomise the label classes (e.g. to hide for visually-hidden labels).

Accessibility

  • The label is a real <label htmlFor="…">; clicking it focuses the input.
  • Description and error ids are merged into the child's aria-describedby; existing ids passed by the caller are preserved.
  • When error is set, the child receives aria-invalid=true automatically.