Components Forms

Form

A form that keeps its values and checks them against rules before onFinish; useForm reaches it from outside, useWatch reads one field.

import { Form, FormItem } from '@kition/tessera-ui'

When to use

  • A settings page, a create or edit dialog, any form with validation.

When not to

  • One setting that applies at once: use a Switch on its own.

Examples

Rules, help, reset

Submit with the email empty to see the errors; they re-check as you type.

Recorded in the credit ledger.

form.tsx
import { Button, Checkbox, Form, FormItem, NumberInput, Select, TextInput, toast, useForm, useWatch } from '@kition/tessera-ui'

type Values = { email: string; credits: number | null; reason: string; plan: string; notify: boolean }

export default function Demo() {
  const form = useForm<Values>()
  const credits = useWatch<number>('credits', form)
  return (
    <div style={{ maxWidth: 420 }}>
      <Form<Values> form={form} initialValues={{ email: '', credits: 100, reason: '', plan: 'pro', notify: true }} onFinish={(values) => toast('success', 'Credits added', `${values.credits} credits for ${values.email}`)}>
        <FormItem name="email" label="Email" rules={[{ required: true }, { type: 'email' }]}>
          <TextInput size="md" placeholder="ada@example.com" />
        </FormItem>
        <FormItem name="credits" label="Credits" rules={[{ required: true }, { min: 1, max: 100000 }]} extra={credits ? `About ${(credits / 100).toFixed(2)} of usage.` : undefined}>
          <NumberInput size="md" min={1} step={10} />
        </FormItem>
        <FormItem name="plan" label="Plan">
          <Select size="md">
            <option value="free">Free</option>
            <option value="pro">Pro</option>
            <option value="team">Team</option>
          </Select>
        </FormItem>
        <FormItem name="reason" label="Reason" rules={[{ required: true, whitespace: true }, { max: 120 }]} extra="Recorded in the credit ledger.">
          <TextInput size="md" />
        </FormItem>
        <FormItem name="notify" valuePropName="checked">
          <Checkbox label="Email the person" />
        </FormItem>
        <div style={{ display: 'flex', gap: 8 }}>
          <Button type="submit" variant="primary" size="md">Add credits</Button>
          <Button size="md" onClick={() => form.resetFields()}>Reset</Button>
        </div>
      </Form>
    </div>
  )
}

Props

Form

A form that keeps its fields' values and checks them before onFinish.

PropTypeDefaultDescription
formFormInstance<T>—
initialValuesPartial<T>—The values it starts with (read once).
onFinish(values: T) => void—Called with the values when the person submits and every field passes.
onValuesChange(changed: Partial<T>, values: T) => void—
layoutFormLayout'vertical'vertical (default): labels above controls; inline: fields in a row (filters).
disabledbooleanfalse
classNamestring—
idstring—
childrenrequiredReactNode—

FormItem

A labelled control bound to one field of the form around it, with its rules and error.

PropTypeDefaultDescription
namestring—The field's name in the values; without it the item only lays out a label and a control.
labelReactNode—
rulesreadonly FormRule[][]
extraReactNode—Help under the control (replaced by the error while there is one).
requiredboolean—Marks the label as required (implied by a required rule).
valuePropNamestring'value'The control's prop that holds the value: checked for a check box or switch.
triggerstring'onChange'The control's prop that reports a change: onCheckedChange for a switch.
getValueFromEvent(...args: any[]) => unknownfromEventThe value from what the control reports (an event's target.value or checked, or the value itself, by default).
dependenciesreadonly string[][]Fields whose changes re-check this one (a confirmation of a password).
hiddenboolean—Kept in the values but not drawn.
classNamestring—
childrenrequiredReactNode—One control element.