Forms Overview
Declarative form state, validation, and UI with useFormDynamic and Form components.
Overview
The Aura Form system gives you a declarative way to handle forms: define field types once, get bound state and handlers, and let the Form component wire validation errors to the right fields. Built on Radix UI Form primitives and designed to work with JSON Schema validation (e.g. AJV).
Motivation
Most form libraries either lock you into a specific validation or UI pattern, or leave you wiring state and errors by hand. Aura Forms aims for:
- Declarative structure – Define your form with field names and types; the hook provides values, touch state, and field props.
- Shared state – One place for values, errors, touch, and submit status so validation and UI stay in sync.
- Automatic error distribution – Pass an array of validation errors to
Form; it matches errors to fields by name and injects them into the right components. - Composable fields – Use
FormFieldfor native inputs, or composed components likeFormFieldSelect,FormFieldCombobox,FormFieldEditor,FormFieldSignaturePad, andFormFieldSortableListthat all consume the samefieldprop.
Architecture
The system has three parts that work together:
flowchart LR
subgraph hook [useFormDynamic]
types[Field types]
value[value state]
touch[touch state]
field[field name to FieldProps]
getFields[getFields]
getValues[getValues]
end
subgraph form [Form]
errors[errors prop]
processChildren[processChildren]
match[instancePath equals field.name]
end
subgraph fields [FormField and FormField components]
fieldProp[field prop]
errorsInjected[errors injected by Form]
end
hook --> getFields
getFields --> fieldProp
errors --> processChildren
processChildren --> match
match --> errorsInjected
fieldProp --> fieldsuseFormDynamic– Defines field types, holds values/touch/error/fetchStatus, and exposesfield(name),getFields(),getValues(),resetForm(), andtouchForm().Form– Receiveserrors(e.g. AJVErrorObject[]), walks its children, and injectserrorsinto any descendant that has afieldprop by matchingerror.instancePath.slice(1)tofield.name.- Form field components – Accept
field(fromgetFields()orfield(name)) and optionalerrors(injected by Form). They usefield.value,field.setValue, and for native inputsfield.onChange/field.onCheckedChange, and show messages whenfield.touch && errors?.length > 0.
Quick example
Minimal form with validation and submit handling:
import { useRef } from "react";
import {
Form,
FormField,
FormSubmit,
FormAlert,
} from "@/components/ui/Form";
import { Input } from "@/components/ui/Input";
import { useFormDynamic } from "@/hooks/use-dynamic-form";
import { validateFormData } from "@/utils/web-validation";
const schema = {
type: "object",
properties: {
name: { type: "string" },
email: { type: "string", format: "email" },
},
required: ["name", "email"],
};
export function QuickForm() {
const formRef = useRef<HTMLFormElement>(null);
const formData = useFormDynamic({
name: "text",
email: "text",
});
const { name, email } = formData.getFields();
const { isValid, errors } = validateFormData(schema, formData.getValues());
const formErrors = errors ?? undefined;
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
formData.setFetchStatus("loading");
if (!isValid) {
formData.setFetchStatus("error");
formData.touchForm();
formData.setError("Please complete all required fields");
return;
}
// Simulate or call your API
await new Promise((r) => setTimeout(r, 500));
formData.setFetchStatus("success");
};
return (
<Form
ref={formRef}
onSubmit={handleSubmit}
errors={formErrors}
id="quick-form"
className="flex flex-col gap-1"
>
<FormAlert
formData={{
fetchStatus: formData.fetchStatus,
error: formData.error,
}}
/>
<FormField field={name} label="Name *">
<Input type="text" placeholder="Your name" />
</FormField>
<FormField field={email} label="Email *">
<Input type="email" placeholder="your@email.com" />
</FormField>
<FormSubmit
fetchStatus={formData.fetchStatus}
buttonProps={{ children: "Submit" }}
form="quick-form"
/>
</Form>
);
}Next steps
- useFormDynamic – Hook API, parameters, return value, and
FieldProps. - Form components –
Form,FormSubmit,FormAlert,FormField,FormSwitch,FormCheckbox, and groups. - Form field composition –
FormFieldSelect,FormFieldCombobox,FormFieldEditor,FormFieldSignaturePad,FormFieldSortableList. - Validation –
validateFormData, error shape, touch behavior, and form-level errors.
For installation and more demos, see Form (component).