Components
Field
Field is layout only. It generates no id, htmlFor or aria-describedby for you — associating a label, a description and an error message with its control is the consumer's job, and every example below does it explicitly.
Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
Installation
npx shadcn@latest add @dr-ui/fieldRegistry dependencies
@dr-ui/utils
@dr-ui/label
@dr-ui/separator
Dependencies
class-variance-authority@^0.7.1
Basic
Invalid
Accessibility
Wire every field by hand:
- Give the control an
idand pointFieldLabelat it withhtmlFor. Aplaceholderis not a label: it is a weak fallback for the accessible name and it disappears as soon as the user types. - Give
FieldDescriptionandFieldErroranidand list those ids in the control'saria-describedby(space-separated when both are present). - Set
aria-invalid='true'on the control while it is invalid.FieldErrorrendersrole='alert', so the message is announced when it appears;aria-describedbyis what keeps it available as the field's description afterwards.
<Field data-invalid='true'>
<FieldLabel htmlFor='password'>Password</FieldLabel>
<Input
id='password'
type='password'
aria-invalid='true'
aria-describedby='password-error'
/>
<FieldError id='password-error'>
Password must be at least 8 characters.
</FieldError>
</Field>Inside a reusable component, generate the ids with React's useId instead of hardcoding them.