Forms
Zen provides a complete form system built on react-hook-form. The Form and FormField components handle validation, error display, and field state management with minimal boilerplate.
How it works#
The form system consists of several components that work together:
- Form - Wraps your form and provides react-hook-form context
- FormField - Connects any input component to the form with automatic value binding and validation
- FormButtons - Container for form action buttons
- FormSubmitButton - Submit button with automatic loading and disabled states
- FormResetButton - Reset button that clears the form to default values
Basic usage#
Wrap your inputs with FormField components inside a Form. Each FormField needs a name that corresponds to a key in your form data.
Validation#
Add validation rules to FormField using the rules prop. This uses react-hook-form's validation API.
Common validation rules#
| Rule | Description |
|---|---|
required | Field must have a value |
min | Minimum value for numbers |
max | Maximum value for numbers |
minLength | Minimum string length |
maxLength | Maximum string length |
pattern | Regex pattern to match |
validate | Custom validation function |
Loading states#
FormSubmitButton automatically shows a loading spinner and disables itself while the form is submitting. This happens when your onSubmit handler returns a Promise.
The submit button is automatically disabled when:
- The form has not been modified (
isDirtyis false) - The form has validation errors (
isValidis false) - The form is currently submitting (
isSubmittingis true)
You can override this behavior with the isDisabled prop.
Error handling#
Pass an error prop to Form to display an error banner above the form. This is useful for showing server-side validation errors or API failures.
All form inputs#
FormField works with all Zen input components. The field automatically binds the value and onChange props.
Dynamic fields with FormFieldArray#
Use FormFieldArray when you need to manage a list of fields that can be added or removed dynamically.
Accessing form state#
The Form component accepts a render function as children, giving you access to the full react-hook-form API.
Schema validation#
Use the resolver prop to integrate with schema validation libraries like Zod or Yup.
Controlled forms#
Use the values prop instead of defaultValues when you need to control form values externally. The form will reset when the values change.
Preventing enter key submission#
Use preventSubmit to stop the form from submitting when the user presses Enter. Useful for forms where you want explicit button clicks only.
Component props#
Form#
| Name | Type | Description |
|---|---|---|
| defaultValues | object | Initial form values (uncontrolled) |
| values | object | Current form values (controlled) |
| onSubmit | (data) => void | Promise | Called when form is submitted with valid data |
| error | ReactNode | Error | Error message to display above the form |
| preventSubmit | boolean | Prevents form submission on Enter key |
| resolver | Resolver | Validation resolver for schema validation (Zod, Yup, etc.) |
| mode | string | Validation mode: "onSubmit" | "onBlur" | "onChange" | "onTouched" | "all" |
FormField#
| Name | Type | Description |
|---|---|---|
| name | string | Field name (required). Must match a key in form values. |
| label | string | Label displayed above the input |
| description | string | Help text displayed below the input |
| rules | RegisterOptions | Validation rules (required, min, max, pattern, validate, etc.) |
FormFieldArray#
| Name | Type | Description |
|---|---|---|
| name | string | Field array name (required) |
| label | string | Label displayed above the field array |
| description | string | Help text displayed below the label |
| children | (props) => ReactNode | Render function receiving fields, append, remove, and control |
FormSubmitButton#
| Name | Type | Description |
|---|---|---|
| variant | ButtonVariant | Button style variant (default: "primary") |
| isDisabled | boolean | Override automatic disabled state |
| isLoading | boolean | Override automatic loading state |
FormResetButton#
| Name | Type | Description |
|---|---|---|
| values | object | Values to reset the form to (default: original defaultValues) |
