Field
A label, control, description and error, connected for screen readers.
Example
We send the invite here.
Installation
pnpm dlx shadcn@latest add superzero11/uiset/fieldIt lands in components/ui/field.tsx, with UISet’s root (uiset). Wrap your app in <UISet> once, and every component takes its skin.
What UISet adds
The component is UI SDK’s own, with its parts, props and names, so everything below works as UI SDK documents it. UISet adds the look and checks it:
- Styles in five skins, each in light and dark, from CSS variables you can override.
- Text at 4.5:1 contrast and control edges and focus rings at 3:1, in every skin and theme, checked with axe in tests.
- Haptic cues on phones, and sound cues when you set
soundon<UISet>. - Examples that name every control, so agents can find it (see Agents below).
The API reference and accessibility notes below are UI SDK’s, from its docs for @ui-sdk/react (Apache-2.0). Field on ui-sdk.dev has more usage examples. Your coding agent can read the same page at node_modules/@ui-sdk/react/docs/components/field.md.
API Reference
Props are the same as below, as React props.
A field has no change events. Read its state from the parts' data attributes, or from render functions. Set debug to log every state change and its reason.
Field
name?(string): The name the control submits under, when the control doesn't set its own.disabled?(boolean): Disables the control, and marks every part.invalid?(boolean): Whether the field shows as invalid, when your code decides, like a form library or an error from the server.trueshows its errors now,falseshows none whatever the browser thinks. Leave it out to show the browser's own validation once a submit finds the field invalid.debug?(boolean): Logs every state change with its reason to the console, in development builds.
FieldError
match?(boolean | ValidityKey): When this error shows.trueshows it always andfalsenever. A validity flag, like"valueMissing", shows it only for that problem of the browser's own validation. Without it, any problem shows it.
FieldSet
disabled?(boolean): Disables every control inside it, except those in its legend, and leaves them out of the form.debug?(boolean): Logs every state change with its reason to the console, in development builds.
State
-
disabled(boolean): Whether the field is disabled, by itself or by a<fieldset>. -
required(boolean): Whether the control is required, read from itsrequiredoraria-required. -
focused(boolean): Whether focus is inside the control. -
invalid(boolean): Whether the field shows as invalid:invalidwhen you pass it, else the browser's validation once shown. -
valid(boolean): Whether the browser's validation passes, once shown. Always false while you passinvalid. -
disabled(boolean): Whether the field is disabled, by itself or by a<fieldset>. -
required(boolean): Whether the control is required, read from itsrequiredoraria-required. -
focused(boolean): Whether focus is inside the control. -
invalid(boolean): Whether the field shows as invalid:invalidwhen you pass it, else the browser's validation once shown. -
valid(boolean): Whether the browser's validation passes, once shown. Always false while you passinvalid. -
message(string): The browser's message for the current problem. Children you pass show instead.
A FieldDescription receives the field's state, or only disabled when it describes a field set.
disabled(boolean): Whether the field set is disabled, by itself or by a field set around it. Whether the field is disabled, by itself or by a<fieldset>.required(boolean | undefined): Whether the control is required, read from itsrequiredoraria-required.focused(boolean | undefined): Whether focus is inside the control.invalid(boolean | undefined): Whether the field shows as invalid:invalidwhen you pass it, else the browser's validation once shown.valid(boolean | undefined): Whether the browser's validation passes, once shown. Always false while you passinvalid.
Every part of a field set receives the same state.
disabled(boolean): Whether the field set is disabled, by itself or by a field set around it.
Accessibility
The label names the control with aria-labelledby, beside a native <label for> where the control can take one. The description and any error that shows describe it with aria-describedby, and an invalid control has aria-invalid. The tests below cover these connections and keyboard behavior.
Labelling
- The label names the control.
- The description describes the control.
- Clicking the label of a text field focuses it.
A label wrapping a field
- Names the control inside it.
- Checks its control when clicked anywhere.
- Keeps the field's description on its control.
- Names a control that renders after it.
- Keeps the part's data-slot.
- Warns in development only when a label outside a field labels nothing.
- A description and an error outside a field keep their data-slot. Web components only.
- A hidden error outside a field stays hidden whatever display its class gives. Web components only.
- An error outside a field follows its match. Web components only.
- An error outside a field shows a child that arrives after it. Web components only.
Errors
- Stay hidden until the form tries to submit.
- Show the browser's message when they have no text of their own.
- Count another library's form-associated element inside the field.
- Describe the control while they show.
- Update as the value changes once shown.
- Update as state set from script changes the value once shown. Web components only.
- A field marked invalid shows its error right away.
- A field marked valid never shows the browser's errors.
- A form reset hides them again.
- Errors in the page replace the browser's message, and the first invalid control takes focus.
Runs in React, Vue and web components.
In a field set:
- The legend names the group.
- A disabled field set disables the controls inside and leaves them out of the form.
- Enabling it again restores the controls.
- A field set disabled from the start disables its required fields.
- Fields in a disabled field set mark their parts disabled.
Enhancements
- The description describes the group.
Runs in React, Vue and web components.
In a form:
- The form submits every checked control's name and value.
- Unchecked controls submit nothing.
- A checkbox outside the form joins it with the form attribute.
- Required controls block submission.
- A form reset returns every control to its default.
- A reset returns to the default value, not to nothing.
- A disabled fieldset disables the controls inside it.
- A read-only control still submits.
- A user's change fires native input and change events on the form.
Runs in React, Vue and web components.
Agents
UI SDK’s agent bridge finds this component by its accessible name: give it a visible label or an aria-label, and an agent can read its state and call its actions without screenshots. Building with AI agents shows how to connect one.
This is agent.snapshot() for the example above, read live from this page. Change something in the example, then read it again: the values follow.
[
{
"ref": "c8",
"component": "input",
"actions": [
"setValue",
"clear"
],
"label": "Work email",
"value": ""
}
]