All components (204)
Form
Fields · Form
What it is and when to use it
Form validates an entire form with a single schema (schema), the same one the server uses, and places each error where it belongs. It is submitted with SubmitButton.
When to use it
- A screen with several fields submitted together: a sign-up, a payment, a contact form.
- When you already have the server's validation schema: it is reused as is, without repeating the rules.
When not to
- A single field that saves when it loses focus: use the field directly with its
onChange. - A search box or a filter: that is not a form that gets submitted.
What it does without being asked: an error summary at the top with role="alert", each field's error under its field, focus on the first one that fails, SubmitButton in loading state while submitting (so it cannot be submitted twice), and whatever onSubmit returns (errors per field or a general error) placed where it goes. By default it validates on submit; validateOn changes it to onBlur or onChange, and summary={false} removes the summary.
It does not depend on any validation library: it works through Standard Schema, so any schema that complies is valid. The library imports none.
And the safety belt: browser validation is a convenience, not security. The same schema has to run on the server — with a curl the whole form is bypassed.
Keyboard: Tab goes through the fields in document order; Enter submits from any single-line field. When submitting with errors, focus jumps to the first one that fails.
Accessibility: each error is associated with its field through aria-describedby and the field is marked invalid. The summary is announced on submit, not before.
Connected fields: text (FormTextField, FormTextArea, FormPasswordField, FormPhoneField, FormDocumentField, FormIbanField, FormCodeField), numeric (FormNumberField, FormQuantityPicker, FormSlider, FormRating), choice (FormSelect, FormMultiSelect, FormSearchField, FormRadioGroup, FormSegmentedGroup, FormCheckbox, FormSwitch, FormCascader, FormTreeSelect), date, time and color (FormDatePicker, FormDateRangePicker, FormTimeField, FormColorPicker) and composite-value (FormCardField, FormAddressField, FormSignatureField, FormFileUpload). All take name and get their value and their error from the form. For any other field, FormField receives a function that renders whatever you want with value, onChange, onBlur and error.
Fine-tuning: each field keeps its own --amset-field-* CSS variables.
What it looks like
Submit it empty to see the errors.
<Form schema={esquemaAlta} initialValues={{ nombre: '', email: '', acepta: false }} onSubmit={guardar}>
<FormTextField name="nombre" label="First and last name" required />
<FormTextField name="email" label="Email" type="email" required />
<FormCheckbox name="acepta">I accept the terms</FormCheckbox>
<SubmitButton>Register</SubmitButton>
</Form>Props
Import it with import { Form } from '@amset/ui/form'. Required props are marked.
| Prop | Type | What it does |
|---|---|---|
schemarequired | StandardSchema | Standard Schema (Zod 4, Valibot...). The same one that validates the server. |
initialValues | DefaultValues<TValues> | — |
onSubmitrequired | (values: TValues) => void | SubmitResponse | Promise<void | SubmitResponse> | Called only with the data already validated. If it returns `errors`, they are drawn in their fields; if it returns `error`, it appears in the summary at the top. |
childrenrequired | ReactNode | — |
summary | boolean | Summary of errors at the top of the form. It is announced on submit. |
className | string | — |
validateOn | 'onSubmit' | 'onBlur' | 'onChange' | When it is validated: on submit (the default) or on leaving each field. |
It also accepts the attributes of the element it renders: className, style, data-*, aria-* and its events.
In the test bench
Every state and variant, to try one at a time, on its page at ui.amset.tech:
