Forms
Build a settings form from nxds components. The form comes in three versions: plain React state, React Hook Form and TanStack Form.
Field holds a label, a control, help text and an error. FieldSet and FieldLegend group related fields.
1. Choose one implementation
| Need | Copy | Component folders | Additional dependency |
|---|---|---|---|
| A small settings form with local React state | settings-form.tsx, settings-layout.tsx and settings-fields.tsx | button, button-group/button-group-context.ts, checkbox, field, input, label, separator, spinner and lib/ | None beyond nxds and React |
| Your app uses React Hook Form | react-hook-form.tsx, settings-layout.tsx and settings-fields.tsx | button, button-group/button-group-context.ts, checkbox, field, input, label, separator, spinner and lib/ | react-hook-form 7 |
| Your app uses TanStack Form | tanstack-form.tsx, settings-layout.tsx and settings-fields.tsx | button, button-group/button-group-context.ts, checkbox, field, input, label, separator, spinner and lib/ | @tanstack/react-form 1 |
| Read-only details or temporarily unavailable settings | settings-display.tsx | checkbox, description-list, field, input, label, separator and lib/ | None beyond nxds and React |
Copy only the version your app uses. settings-layout.tsx holds the shared types, validation rules, and the status, Save and Cancel buttons. settings-fields.tsx renders the fields.
2. Connect application data
All three versions take the same props:
| Prop | Does |
|---|---|
title | Names the form. Give each form on a page its own title. |
initialValues | Sets the starting values. Changing it later doesn’t overwrite what the user is typing. To load a different record, change the form’s key. |
onSave | Saves the values. Must resolve with the saved record, or reject if the save fails. |
With fetch, throw when response.ok is false. Parse the response into the SettingsValues shape before you resolve. If your API wraps the record, like { data: … }, unwrap it first.
After a save, the form shows the record you resolved with, so changes your server made replace what the user typed. Fields the form doesn’t edit are ignored.
If the save fails, the user’s edits stay so they can retry. Cancel restores the last saved values. Save is blocked while a save is running.
Local state
Edit a field to enable Save. To see validation, clear the name or enter an invalid email, then save.
Checkboxes don’t save until the user clicks Save. Use a switch only for a change that applies immediately.
Form libraries
Both versions behave like the local-state form. They validate on save, focus the first invalid field, and clear an error when the field is edited.
React Hook Form
Uses useForm and useController.
TanStack Form
Uses useForm and useField. It detects unsaved changes with !isDefaultValue.
Read-only and disabled
Read-only details
Use a DescriptionList for values the user can read but not edit. Say who can change them, and show empty values as “Not provided” instead of leaving them blank.
Account details
These details are managed by your organization. Contact an administrator to change them.
- Name
- Priya Shah
- priya@example.com
- Team
- Not provided
Temporarily unavailable
Disable a control only when it’s temporarily unavailable. Show the reason, and link the reason to the control with aria-describedby.
What your app owns
- Permissions, server validation, loading data, leave-page warnings and saving. Replace the sample fields and validation rules with your own.
- Error messages. A failed save shows a fixed message, never the error’s own text. To show server errors, edit the submit handler.
- The source lives in
packages/react/src/patterns/forms. Update its imports to point at your copied components.
The forms on this page don’t save anything.