Forms · Validation
Validation
Every message has one home. Required and format errors sit under the field, a failed submit produces a summary with links back to the offending fields, and the server's own failure is a form-level message — not a toast that vanishes.
import { Fieldset, FormActions, Input, SubmitButton, Switch, Textarea } from "@luc/ui";Examples
Field rules, field messages
Required, minimum length, numeric shape and cross-field rules all report through the same `error` slot, so the form never grows four different error styles.
<RhfForm form={form} fieldLabels={labels} onSubmit={save}>
<FormField name="name" label="Study name" rules={{ required: "Give the study a name" }} />
<FormField
name="symbol"
label="Instrument"
rules={{ validate: (value) => (SYMBOLS.includes(value) ? undefined : "Unsupported instrument") }}
>
{({ controlProps }) => <Input placeholder="BTC-USD" {...controlProps} />}
</FormField>
<FormField
name="lookback"
label="Lookback (days)"
description="Whole days between 5 and 400."
rules={{ required: "Enter a lookback" }}
/>
</RhfForm>Server errors are form-level
When the save itself fails, the message belongs to the form. The demo throws on the second attempt so you can see the difference between validation and rejection.
<ServerErrorDemo />Usage
import { FormField, RhfForm } from "@luc/ui/forms/react-hook-form";<RhfForm form={form} fieldLabels={{ name: "Study name" }} onSubmit={save}>
<FormField name="name" label="Study name" rules={{ required: "Give the study a name" }}>
{({ controlProps }) => <Input {...controlProps} />}
</FormField>
<FormActions>
<SubmitButton loadingText="Saving">Save study</SubmitButton>
</FormActions>
</RhfForm>`FormField` takes a `name`, a `label` and the engine's `rules`; `fieldLabels` names the fields inside the error summary, because a summary that lists `symbol` instead of “Instrument” is a summary nobody can act on.
API
This page shows components working together rather than exporting one of its own, so the props live on the pages below — each link opens that page's API table.
Guidelines
Every message has one home: a field rule reports under its field, a failed submit fills the summary — which appears only after an attempt, never while the form is still being filled in — and a rejected save is a form-level message. Nothing here validates with a toast.
Field messages come from the form engine; the summary is Luc UI's, and a plain form renders it by passing its own errors array.