Input
Examples
Input fields
Input sizes
Disabled state
Required and optional
Mark the required side with a Required badge on the label, and say "Optional" in a FieldDescription — never an asterisk, which carries no meaning to a screen reader on its own. Pick one per form and stay with it: if most fields are required, label the few optional ones instead of badging everything.
required on the control itself is separate — it drives native validation and aria-required, and should be set whether or not the badge is shown.
Invalid state
aria-invalid paints the state. By default the control itself carries it — a tinted fill and a solid edge — so the field reads as wrong at a glance rather than relying on a ring the eye can skip. The message is a FieldError below it, plain text beside an icon.
A floating label turns destructive with it, in both treatments; that belongs to the control and is unchanged here. Valid takes the fill and the edge but leaves the label alone — an error has to interrupt, a confirmation only has to be noticed, and a green label on every settled field is as hard to scan as a wall of red.
stateStyle="halo" on the Field is the alternative: the control stays on the card surface with a soft outline, and the message rides in a tinted panel tucked up behind it so the two read as one shape. Reach for it where the fill would fight a busy surface.
Valid state
The mirror of the invalid state, in green, and it takes the same two treatments. data-valid is a data attribute rather than an ARIA one because ARIA has no affirmative counterpart to aria-invalid — there is nothing to announce until there is a message to announce.
It comes at two volumes, and the quiet one is the default. data-valid="quiet" is a tick at the trailing edge of the control and nothing else: no halo, no border, no panel, no reflow. Several fields can carry it at once without the form reading as a wall of green, which is exactly what makes it the one to reach for after a format check or a lookup that simply came back fine.
data-valid="true" is the loud one: the full halo, plus a FieldSuccess that tucks behind the control the way a FieldError does and announces politely (role="status"). Spend it on the one answer worth a sentence — username free, code accepted, address found. Spend it twice on the same form and you have spent it nowhere, and a wall of green is as hard to scan as a wall of red.