DEVELOPMENT PREVIEWIn development

Form

Validation caught before submission, inline at the fields — never as after-the-fact toasts. Try submitting the demo empty.

Sign-up form — submit it empty

At least 8 characters.
Snippet
import { Form, TextInput, Checkbox, Button } from '@creo-team/buzz-ui/client'

<Form
  onSubmit={values => api.signUp(values)}   // only fires when valid
  validate={{
    password: value =>
      value.length < 8 ? 'Use at least 8 characters.' : undefined,
    confirm: (value, values) =>
      value !== values.password ? 'Passwords do not match.' : undefined,
  }}
>
  <TextInput name="email" label="Email" type="email" required />
  <TextInput name="password" label="Password" type="password" required />
  <TextInput name="confirm" label="Confirm password" type="password" required />
  <Checkbox name="tos" label="I accept the terms" required />
  <Button type="submit">Create account</Button>
</Form>

How validation flows

  • Reward early, punish late. Typing is never interrupted before the first submit attempt. After a failed attempt, fields re-validate on every change, so errors disappear the moment they're fixed.
  • Browser rules first. required, type="email", minLength, pattern… run with the browser's own localized messages, then your validate functions run per field.
  • Cross-field rules are one-liners. Validators receive every field's value — password confirmation needs no extra state, and fixing either side clears the error.
  • No registration. Any control with a name participates — Buzz UI inputs, native elements, checkbox groups (arrays), Combobox. The first invalid control is focused for you.
  • Server actions welcome. Omit onSubmit and pass action instead — validation still gates the native submission.

Custom controls

Building your own control? Read the surrounding form's error for a name with useFormField, or render the standard inline message with FormFieldError:

Snippet
import { useFormField, FormFieldError } from '@creo-team/buzz-ui/client'

function ColorPicker({ name }: { name: string }) {
  const { error } = useFormField(name)
  return (
    <div>
      <input type="color" name={name} aria-invalid={error ? true : undefined} />
      <FormFieldError name={name} />
    </div>
  )
}

API Reference

PropTypeDefaultDescription
onSubmit
(values: FormValues, event) => void—Called with collected values only after every field passes. Prevents native submission.
validate
Record<string, (value, values) => string | undefined>—Per-field validators keyed by control name, run after browser constraint validation.
onValidityChange
(errors: Record<string, string>) => void—Observes the error map as it changes.
...props
React.FormHTMLAttributes<HTMLFormElement>—All standard form attributes, including action for server actions.